scada-common annotation updates
This commit is contained in:
parent
fb56634fc4
commit
3003e57531
@ -6,10 +6,10 @@
|
||||
|
||||
-- note: max samples = 0x20000 (128 * 1024 samples)
|
||||
|
||||
local _2_PI = 2 * math.pi -- 2 whole pies, hope you're hungry
|
||||
local _DRATE = 48000 -- 48kHz audio
|
||||
local _MAX_VAL = 127 / 2 -- max signed integer in this 8-bit audio
|
||||
local _05s_SAMPLES = 24000 -- half a second worth of samples
|
||||
local _2_PI = 2 * math.pi -- 2 whole pies, hope you're hungry
|
||||
local _DRATE = 48000 -- 48kHz audio data rate
|
||||
local _MAX_VAL = 127 / 2 -- max signed integer in this 8-bit audio
|
||||
local _05s_SAMPLES = 24000 -- half a second worth of samples
|
||||
|
||||
---@class audio
|
||||
local audio = {}
|
||||
@ -28,6 +28,7 @@ local TONE = {
|
||||
|
||||
audio.TONE = TONE
|
||||
|
||||
---@type integer[][][]
|
||||
local tone_data = {
|
||||
{ {}, {}, {}, {} }, -- 340Hz @ 2Hz Intermittent
|
||||
{ {}, {}, {}, {} }, -- 544Hz 100mS / 440Hz 400mS Alternating
|
||||
@ -214,7 +215,14 @@ end
|
||||
|
||||
-- generate all 8 tone sequences
|
||||
function audio.generate_tones()
|
||||
gen_tone_1(); gen_tone_2(); gen_tone_3(); gen_tone_4(); gen_tone_5(); gen_tone_6(); gen_tone_7(); gen_tone_8()
|
||||
gen_tone_1()
|
||||
gen_tone_2()
|
||||
gen_tone_3()
|
||||
gen_tone_4()
|
||||
gen_tone_5()
|
||||
gen_tone_6()
|
||||
gen_tone_7()
|
||||
gen_tone_8()
|
||||
end
|
||||
|
||||
-- hard audio limiter
|
||||
@ -226,7 +234,7 @@ local function limit(output)
|
||||
end
|
||||
|
||||
-- clear output buffer
|
||||
---@param buffer table quad buffer
|
||||
---@param buffer integer[][] quad buffer
|
||||
local function clear(buffer)
|
||||
for i = 1, 4 do
|
||||
for s = 1, _05s_SAMPLES do buffer[i][s] = 0 end
|
||||
@ -239,7 +247,7 @@ function audio.new_stream()
|
||||
any_active = false,
|
||||
need_recompute = false,
|
||||
next_block = 1,
|
||||
-- split audio up into 0.5s samples, so specific components can be ended quicker
|
||||
---@type integer[][] split audio up into 0.5s samples, so specific components can be ended quicker
|
||||
quad_buffer = { {}, {}, {}, {} },
|
||||
-- all tone enable states
|
||||
tone_active = { false, false, false, false, false, false, false, false }
|
||||
@ -263,14 +271,17 @@ function audio.new_stream()
|
||||
-- check if a tone is active
|
||||
---@param index TONE tone index
|
||||
function public.is_active(index)
|
||||
if self.tone_active[index] then return self.tone_active[index] end
|
||||
return false
|
||||
return self.tone_active[index] or false
|
||||
end
|
||||
|
||||
-- set all tones inactive, reset next block, and clear output buffer
|
||||
function public.stop()
|
||||
for i = 1, #self.tone_active do self.tone_active[i] = false end
|
||||
for i = 1, #self.tone_active do
|
||||
self.tone_active[i] = false
|
||||
end
|
||||
|
||||
self.next_block = 1
|
||||
|
||||
clear(self.quad_buffer)
|
||||
end
|
||||
|
||||
@ -287,9 +298,11 @@ function audio.new_stream()
|
||||
for id = 1, #tone_data do
|
||||
if self.tone_active[id] then
|
||||
self.any_active = true
|
||||
|
||||
for i = 1, 4 do
|
||||
local buffer = self.quad_buffer[i]
|
||||
local values = tone_data[id][i]
|
||||
|
||||
for s = 1, _05s_SAMPLES do self.quad_buffer[i][s] = limit(buffer[s] + values[s]) end
|
||||
end
|
||||
end
|
||||
@ -305,8 +318,13 @@ function audio.new_stream()
|
||||
-- get the next audio block
|
||||
function public.get_next_block()
|
||||
local block = self.quad_buffer[self.next_block]
|
||||
|
||||
self.next_block = self.next_block + 1
|
||||
if self.next_block > 4 then self.next_block = 1 end
|
||||
|
||||
if self.next_block > 4 then
|
||||
self.next_block = 1
|
||||
end
|
||||
|
||||
return block
|
||||
end
|
||||
|
||||
|
||||
@ -405,7 +405,7 @@ function comms.modbus_packet()
|
||||
self.raw = { self.txn_id, self.unit_id, self.func_code }
|
||||
for i = 1, self.length do insert(self.raw, data[i]) end
|
||||
else
|
||||
log.error("comms.modbus_packet.make(): data not table")
|
||||
log.error("comms.modbus_packet.make(): data not a table")
|
||||
end
|
||||
end
|
||||
|
||||
@ -491,7 +491,7 @@ function comms.rplc_packet()
|
||||
self.raw = { self.id, self.type }
|
||||
for i = 1, #data do insert(self.raw, data[i]) end
|
||||
else
|
||||
log.error("comms.rplc_packet.make(): data not table")
|
||||
log.error("comms.rplc_packet.make(): data not a table")
|
||||
end
|
||||
end
|
||||
|
||||
@ -573,7 +573,7 @@ function comms.mgmt_packet()
|
||||
self.raw = { self.type }
|
||||
for i = 1, #data do insert(self.raw, data[i]) end
|
||||
else
|
||||
log.error("comms.mgmt_packet.make(): data not table")
|
||||
log.error("comms.mgmt_packet.make(): data not a table")
|
||||
end
|
||||
end
|
||||
|
||||
@ -652,7 +652,7 @@ function comms.crdn_packet()
|
||||
self.raw = { self.type }
|
||||
for i = 1, #data do insert(self.raw, data[i]) end
|
||||
else
|
||||
log.error("comms.crdn_packet.make(): data not table")
|
||||
log.error("comms.crdn_packet.make(): data not a table")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ local util = require("scada-common.util")
|
||||
---@class logger
|
||||
local log = {}
|
||||
|
||||
---@alias MODE integer
|
||||
---@enum MODE
|
||||
local MODE = { APPEND = 0, NEW = 1 }
|
||||
|
||||
log.MODE = MODE
|
||||
@ -18,7 +18,7 @@ local logger = {
|
||||
mode = MODE.APPEND,
|
||||
debug = false,
|
||||
file = nil, ---@type table|nil
|
||||
dmesg_out = nil,
|
||||
dmesg_out = nil, ---@type table|nil
|
||||
dmesg_restore_coord = { 1, 1 },
|
||||
dmesg_scroll_count = 0
|
||||
}
|
||||
@ -37,7 +37,7 @@ local function _log(msg)
|
||||
|
||||
local out_of_space = false
|
||||
local time_stamp = os.date("[%c] ")
|
||||
local stamped = time_stamp .. util.strval(msg)
|
||||
local stamped = util.c(time_stamp, msg)
|
||||
|
||||
-- attempt to write log
|
||||
local status, result = pcall(function ()
|
||||
@ -291,7 +291,7 @@ function log.dmesg_working(msg, tag, tag_color)
|
||||
end
|
||||
|
||||
-- log debug messages
|
||||
---@param msg string message
|
||||
---@param msg any message
|
||||
---@param trace? boolean include file trace
|
||||
function log.debug(msg, trace)
|
||||
if logger.debug then
|
||||
@ -302,30 +302,30 @@ function log.debug(msg, trace)
|
||||
local name = ""
|
||||
|
||||
if info.name ~= nil then
|
||||
name = ":" .. info.name .. "():"
|
||||
name = util.c(":", info.name, "():")
|
||||
end
|
||||
|
||||
dbg_info = info.short_src .. ":" .. name .. info.currentline .. " > "
|
||||
dbg_info = util.c(info.short_src, ":", name, info.currentline, " > ")
|
||||
end
|
||||
|
||||
_log("[DBG] " .. dbg_info .. util.strval(msg))
|
||||
_log(util.c("[DBG] ", dbg_info, msg))
|
||||
end
|
||||
end
|
||||
|
||||
-- log info messages
|
||||
---@param msg string message
|
||||
---@param msg any message
|
||||
function log.info(msg)
|
||||
_log("[INF] " .. util.strval(msg))
|
||||
_log(util.c("[INF] ", msg))
|
||||
end
|
||||
|
||||
-- log warning messages
|
||||
---@param msg string message
|
||||
---@param msg any message
|
||||
function log.warning(msg)
|
||||
_log("[WRN] " .. util.strval(msg))
|
||||
_log(util.c("[WRN] ", msg))
|
||||
end
|
||||
|
||||
-- log error messages
|
||||
---@param msg string message
|
||||
---@param msg any message
|
||||
---@param trace? boolean include file trace
|
||||
function log.error(msg, trace)
|
||||
local dbg_info = ""
|
||||
@ -335,19 +335,19 @@ function log.error(msg, trace)
|
||||
local name = ""
|
||||
|
||||
if info.name ~= nil then
|
||||
name = ":" .. info.name .. "():"
|
||||
name = util.c(":", info.name, "():")
|
||||
end
|
||||
|
||||
dbg_info = info.short_src .. ":" .. name .. info.currentline .. " > "
|
||||
dbg_info = util.c(info.short_src, ":", name, info.currentline, " > ")
|
||||
end
|
||||
|
||||
_log("[ERR] " .. dbg_info .. util.strval(msg))
|
||||
_log(util.c("[ERR] ", dbg_info, msg))
|
||||
end
|
||||
|
||||
-- log fatal errors
|
||||
---@param msg string message
|
||||
---@param msg any message
|
||||
function log.fatal(msg)
|
||||
_log("[FTL] " .. util.strval(msg))
|
||||
_log(util.c("[FTL] ", msg))
|
||||
end
|
||||
|
||||
return log
|
||||
|
||||
@ -27,6 +27,7 @@ local remove = table.remove
|
||||
-- create a new message queue
|
||||
---@nodiscard
|
||||
function mqueue.new()
|
||||
---@type queue_item[]
|
||||
local queue = {}
|
||||
|
||||
---@class mqueue
|
||||
|
||||
@ -85,18 +85,15 @@ function network.nic(modem)
|
||||
}
|
||||
|
||||
---@class nic
|
||||
---@field open function
|
||||
---@field isOpen function
|
||||
---@field close function
|
||||
---@field closeAll function
|
||||
---@field isWireless function
|
||||
---@field getNameLocal function
|
||||
---@field getNamesRemote function
|
||||
---@field isPresentRemote function
|
||||
---@field getTypeRemote function
|
||||
---@field hasTypeRemote function
|
||||
---@field getMethodsRemote function
|
||||
---@field callRemote function
|
||||
---@field isOpen fun(channel: integer) : boolean check if a channel is open
|
||||
---@field isWireless fun() : boolean determine if this is a wired or wireless modem
|
||||
---@field getNamesRemote fun() : string[] list all remote peripherals on the wired network
|
||||
---@field isPresentRemote fun(name: string) : boolean determine if a peripheral is available on this wired network
|
||||
---@field getTypeRemote fun(name: string) : string|nil get the type of a peripheral is available on this wired network
|
||||
---@field hasTypeRemote fun(name: string, type: string) : boolean|nil check a peripheral is of a particular type
|
||||
---@field getMethodsRemote fun(name: string) : string[] get all available methods for the remote peripheral with the given name
|
||||
---@field callRemote fun(remoteName: string, method: string, ...) : table call a method on a peripheral on this wired network
|
||||
---@field getNameLocal fun() : string|nil returns the network name of the current computer, if the modem is on
|
||||
local public = {}
|
||||
|
||||
-- check if this NIC has a connected modem
|
||||
|
||||
@ -23,7 +23,7 @@ ppm.VIRTUAL_DEVICE_TYPE = VIRTUAL_DEVICE_TYPE
|
||||
local REPORT_FREQUENCY = 20 -- log every 20 faults per function
|
||||
|
||||
local ppm_sys = {
|
||||
mounts = {},
|
||||
mounts = {}, ---@type { [string]: ppm_entry }
|
||||
next_vid = 0,
|
||||
auto_cf = false,
|
||||
faulted = false,
|
||||
@ -40,10 +40,10 @@ local function peri_init(iface)
|
||||
local self = {
|
||||
faulted = false,
|
||||
last_fault = "",
|
||||
fault_counts = {},
|
||||
fault_counts = {}, ---@type { [string]: integer }
|
||||
auto_cf = true,
|
||||
type = VIRTUAL_DEVICE_TYPE,
|
||||
device = {}
|
||||
type = VIRTUAL_DEVICE_TYPE, ---@type string
|
||||
device = {} ---@type { [string]: function }
|
||||
}
|
||||
|
||||
if iface ~= "__virtual__" then
|
||||
@ -181,7 +181,7 @@ local function peri_init(iface)
|
||||
setmetatable(self.device, mt)
|
||||
|
||||
---@class ppm_entry
|
||||
local entry = { type = self.type, dev = self.device }
|
||||
local entry = { type = self.type, dev = self.device }
|
||||
|
||||
return entry
|
||||
end
|
||||
@ -284,10 +284,10 @@ end
|
||||
---@param device table device table
|
||||
function ppm.unmount(device)
|
||||
if device then
|
||||
for side, data in pairs(ppm_sys.mounts) do
|
||||
for iface, data in pairs(ppm_sys.mounts) do
|
||||
if data.dev == device then
|
||||
log.warning(util.c("PPM: manually unmounted ", data.type, " mounted to ", side))
|
||||
ppm_sys.mounts[side] = nil
|
||||
log.warning(util.c("PPM: manually unmounted ", data.type, " mounted to ", iface))
|
||||
ppm_sys.mounts[iface] = nil
|
||||
break
|
||||
end
|
||||
end
|
||||
@ -352,8 +352,8 @@ end
|
||||
---@return string|nil iface CC peripheral interface
|
||||
function ppm.get_iface(device)
|
||||
if device then
|
||||
for side, data in pairs(ppm_sys.mounts) do
|
||||
if data.dev == device then return side end
|
||||
for iface, data in pairs(ppm_sys.mounts) do
|
||||
if data.dev == device then return iface end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -6,9 +6,10 @@ local util = require("scada-common.util")
|
||||
|
||||
local psil = {}
|
||||
|
||||
-- instantiate a new PSI layer
|
||||
-- instantiate a new interconnect layer
|
||||
---@nodiscard
|
||||
function psil.create()
|
||||
---@type { [string]: { subscribers: { notify: fun(param: any) }[], value: any } } interconnect table
|
||||
local ic = {}
|
||||
|
||||
-- allocate a new interconnect field
|
||||
|
||||
@ -113,10 +113,13 @@ assert(#dup_chk == rsio.NUM_PORTS, "port list malformed")
|
||||
local IO = IO_PORT
|
||||
|
||||
-- list of all port names
|
||||
---@type string[]
|
||||
local PORT_NAMES = {}
|
||||
|
||||
for k, v in pairs(IO) do PORT_NAMES[v] = k end
|
||||
|
||||
-- list of all port I/O modes
|
||||
---@type { [IO_PORT]: IO_MODE }
|
||||
local MODES = {
|
||||
[IO.F_SCRAM] = IO_MODE.DIGITAL_IN,
|
||||
[IO.F_ACK] = IO_MODE.DIGITAL_IN,
|
||||
@ -233,6 +236,7 @@ end
|
||||
|
||||
--#region Generic Checks
|
||||
|
||||
---@type string[]
|
||||
local RS_SIDES = rs.getSides()
|
||||
|
||||
-- check if a port is valid
|
||||
|
||||
@ -7,6 +7,7 @@ local util = require("scada-common.util")
|
||||
|
||||
local tcd = {}
|
||||
|
||||
---@type { callback: function, duration: number, expiry: number }[]
|
||||
local registry = {}
|
||||
|
||||
-- request a function to be called after the specified time
|
||||
|
||||
@ -24,7 +24,7 @@ local t_pack = table.pack
|
||||
local util = {}
|
||||
|
||||
-- scada-common version
|
||||
util.version = "1.4.4"
|
||||
util.version = "1.4.5"
|
||||
|
||||
util.TICK_TIME_S = 0.05
|
||||
util.TICK_TIME_MS = 50
|
||||
@ -33,9 +33,9 @@ util.TICK_TIME_MS = 50
|
||||
|
||||
-- trinary operator
|
||||
---@nodiscard
|
||||
---@param cond boolean|nil condition
|
||||
---@param a any return if true
|
||||
---@param b any return if false
|
||||
---@param cond any condition
|
||||
---@param a any return if evaluated as true
|
||||
---@param b any return if false or nil
|
||||
---@return any value
|
||||
function util.trinary(cond, a, b)
|
||||
if cond then return a else return b end
|
||||
@ -84,7 +84,7 @@ end
|
||||
-- does not behave exactly like C's strtok
|
||||
---@param str string string to tokenize
|
||||
---@param sep string separator to tokenize by
|
||||
---@return table token_list
|
||||
---@return string[] token_list
|
||||
function util.strtok(str, sep)
|
||||
local list = {}
|
||||
for part in string.gmatch(str, "([^" .. sep .. "]+)") do t_insert(list, part) end
|
||||
@ -123,7 +123,7 @@ end
|
||||
---@nodiscard
|
||||
---@param str string
|
||||
---@param limit integer line limit, must be greater than 0
|
||||
---@return table lines
|
||||
---@return string[] lines
|
||||
function util.strwrap(str, limit)
|
||||
assert(limit > 0, "util.strwrap() limit not greater than 0")
|
||||
return cc_strings.wrap(str, limit)
|
||||
@ -343,8 +343,9 @@ end
|
||||
|
||||
-- delete elements from a table if the passed function returns false when passed a table element<br>
|
||||
-- put briefly: deletes elements that return false, keeps elements that return true
|
||||
---@param t table table to remove elements from
|
||||
---@param f function should return false to delete an element when passed the element: f(elem) = true|false
|
||||
---@generic Type
|
||||
---@param t Type[] table to remove elements from
|
||||
---@param f fun(t_elem: Type) : boolean should return false to delete an element when passed the element
|
||||
---@param on_delete? function optional function to execute on deletion, passed the table element to be deleted as the parameter
|
||||
function util.filter_table(t, f, on_delete)
|
||||
local move_to = 1
|
||||
@ -366,9 +367,10 @@ function util.filter_table(t, f, on_delete)
|
||||
end
|
||||
|
||||
-- check if a table contains the provided element
|
||||
---@generic Type
|
||||
---@nodiscard
|
||||
---@param t table table to check
|
||||
---@param element any element to check for
|
||||
---@param t Type[] table to check
|
||||
---@param element Type element to check for
|
||||
function util.table_contains(t, element)
|
||||
for i = 1, #t do
|
||||
if t[i] == element then return true end
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user