scada-common annotation updates

This commit is contained in:
Mikayla 2024-09-12 17:47:12 +00:00
parent fb56634fc4
commit 3003e57531
10 changed files with 89 additions and 65 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -27,6 +27,7 @@ local remove = table.remove
-- create a new message queue
---@nodiscard
function mqueue.new()
---@type queue_item[]
local queue = {}
---@class mqueue

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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