Merge pull request #617 from MikaylaFischler/rtu-redstone-enhancements

redstone invert
This commit is contained in:
Mikayla
2025-04-20 17:41:26 -04:00
committed by GitHub
4 changed files with 98 additions and 53 deletions

View File

@ -20,6 +20,7 @@ local NumberField = require("graphics.elements.form.NumberField")
---@field port IO_PORT
---@field side side
---@field color color|nil
---@field invert true|nil
local tri = util.trinary
@ -41,7 +42,9 @@ local self = {
rs_cfg_side_l = nil, ---@type TextBox
rs_cfg_bundled = nil, ---@type Checkbox
rs_cfg_color = nil, ---@type Radio2D
rs_cfg_shortcut = nil ---@type TextBox
rs_cfg_inverted = nil, ---@type Checkbox
rs_cfg_shortcut = nil, ---@type TextBox
rs_cfg_advanced = nil ---@type PushButton
}
-- rsio port descriptions
@ -141,8 +144,9 @@ function redstone.create(tool_ctl, main_pane, cfg_sys, rs_cfg, style)
local rs_c_5 = Div{parent=rs_cfg,x=2,y=4,width=49}
local rs_c_6 = Div{parent=rs_cfg,x=2,y=4,width=49}
local rs_c_7 = Div{parent=rs_cfg,x=2,y=4,width=49}
local rs_c_8 = Div{parent=rs_cfg,x=2,y=4,width=49}
local rs_pane = MultiPane{parent=rs_cfg,x=1,y=4,panes={rs_c_1,rs_c_2,rs_c_3,rs_c_4,rs_c_5,rs_c_6,rs_c_7}}
local rs_pane = MultiPane{parent=rs_cfg,x=1,y=4,panes={rs_c_1,rs_c_2,rs_c_3,rs_c_4,rs_c_5,rs_c_6,rs_c_7,rs_c_8}}
TextBox{parent=rs_cfg,x=1,y=2,text=" Redstone Connections",fg_bg=cpair(colors.black,colors.red)}
@ -175,9 +179,6 @@ function redstone.create(tool_ctl, main_pane, cfg_sys, rs_cfg, style)
PushButton{parent=rs_c_1,x=35,y=14,min_width=7,text="New +",callback=function()rs_pane.set_value(2)end,fg_bg=cpair(colors.black,colors.blue),active_fg_bg=btn_act_fg_bg}
local rs_apply_btn = PushButton{parent=rs_c_1,x=43,y=14,min_width=7,text="Apply",callback=rs_apply,fg_bg=cpair(colors.black,colors.green),active_fg_bg=btn_act_fg_bg,dis_fg_bg=btn_dis_fg_bg}
TextBox{parent=rs_c_6,x=1,y=1,height=5,text="You already configured this input. There can only be one entry for each input.\n\nPlease select a different port."}
PushButton{parent=rs_c_6,x=1,y=14,text="\x1b Back",callback=function()rs_pane.set_value(2)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
TextBox{parent=rs_c_2,x=1,y=1,text="Select one of the below ports to use."}
local rs_ports = ListBox{parent=rs_c_2,x=1,y=3,height=10,width=49,scroll_height=200,fg_bg=bw_fg_bg,nav_fg_bg=g_lg_fg_bg,nav_active=cpair(colors.black,colors.gray)}
@ -200,6 +201,8 @@ function redstone.create(tool_ctl, main_pane, cfg_sys, rs_cfg, style)
self.rs_cfg_color.hide(true)
self.rs_cfg_shortcut.show()
self.rs_cfg_side_l.set_value("Output Side")
self.rs_cfg_bundled.enable()
self.rs_cfg_advanced.disable()
text = "You selected the ALL_WASTE shortcut."
else
self.rs_cfg_shortcut.hide(true)
@ -214,9 +217,13 @@ function redstone.create(tool_ctl, main_pane, cfg_sys, rs_cfg, style)
self.rs_cfg_bundled.set_value(false)
self.rs_cfg_bundled.disable()
self.rs_cfg_color.disable()
self.rs_cfg_inverted.set_value(false)
self.rs_cfg_advanced.disable()
else
self.rs_cfg_bundled.enable()
if self.rs_cfg_bundled.get_value() then self.rs_cfg_color.enable() else self.rs_cfg_color.disable() end
self.rs_cfg_inverted.set_value(false)
self.rs_cfg_advanced.enable()
end
if io_mode == IO_MODE.DIGITAL_IN then
@ -269,11 +276,6 @@ function redstone.create(tool_ctl, main_pane, cfg_sys, rs_cfg, style)
PushButton{parent=rs_c_3,x=36,y=3,text="What's that?",min_width=14,callback=function()rs_pane.set_value(7)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
TextBox{parent=rs_c_7,x=1,y=1,height=4,text="(Normal) Digital Input: On if there is a redstone signal, off otherwise\nInverted Digital Input: On without a redstone signal, off otherwise"}
TextBox{parent=rs_c_7,x=1,y=6,height=4,text="(Normal) Digital Output: Redstone signal to 'turn it on', none to 'turn it off'\nInverted Digital Output: No redstone signal to 'turn it on', redstone signal to 'turn it off'"}
TextBox{parent=rs_c_7,x=1,y=11,height=2,text="Analog Input: 0-15 redstone power level input\nAnalog Output: 0-15 scaled redstone power level output"}
PushButton{parent=rs_c_7,x=1,y=14,text="\x1b Back",callback=function()rs_pane.set_value(3)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
self.rs_cfg_side_l = TextBox{parent=rs_c_3,x=1,y=4,width=11,text="Output Side"}
local side = Radio2D{parent=rs_c_3,x=1,y=5,rows=1,columns=6,default=1,options=side_options,radio_colors=cpair(colors.lightGray,colors.black),select_color=colors.red}
@ -312,7 +314,8 @@ function redstone.create(tool_ctl, main_pane, cfg_sys, rs_cfg, style)
unit = tri(PORT_DSGN[port] == 1, u, nil),
port = port,
side = side_options_map[side.get_value()],
color = tri(self.rs_cfg_bundled.get_value() and rsio.is_digital(port), color_options_map[self.rs_cfg_color.get_value()], nil)
color = tri(self.rs_cfg_bundled.get_value() and rsio.is_digital(port), color_options_map[self.rs_cfg_color.get_value()], nil),
invert = self.rs_cfg_inverted.get_value() or nil
}
if self.rs_cfg_editing == false then
@ -341,10 +344,13 @@ function redstone.create(tool_ctl, main_pane, cfg_sys, rs_cfg, style)
self.rs_cfg_bundled.set_value(false)
self.rs_cfg_color.set_value(1)
self.rs_cfg_color.disable()
self.rs_cfg_inverted.set_value(false)
self.rs_cfg_advanced.disable()
else rs_err.show() end
end
PushButton{parent=rs_c_3,x=1,y=14,text="\x1b Back",callback=back_from_rs_opts,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
self.rs_cfg_advanced = PushButton{parent=rs_c_3,x=30,y=14,min_width=10,text="Advanced",callback=function()rs_pane.set_value(8)end,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=btn_act_fg_bg,dis_fg_bg=btn_dis_fg_bg}
PushButton{parent=rs_c_3,x=41,y=14,min_width=9,text="Confirm",callback=save_rs_entry,fg_bg=cpair(colors.black,colors.blue),active_fg_bg=btn_act_fg_bg}
TextBox{parent=rs_c_4,x=1,y=1,text="Settings saved!"}
@ -355,6 +361,19 @@ function redstone.create(tool_ctl, main_pane, cfg_sys, rs_cfg, style)
PushButton{parent=rs_c_5,x=1,y=14,text="\x1b Back",callback=function()rs_pane.set_value(1)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
PushButton{parent=rs_c_5,x=44,y=14,min_width=6,text="Home",callback=function()tool_ctl.go_home()end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
TextBox{parent=rs_c_6,x=1,y=1,height=5,text="You already configured this input. There can only be one entry for each input.\n\nPlease select a different port."}
PushButton{parent=rs_c_6,x=1,y=14,text="\x1b Back",callback=function()rs_pane.set_value(2)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
TextBox{parent=rs_c_7,x=1,y=1,height=4,text="(Normal) Digital Input: On if there is a redstone signal, off otherwise\nInverted Digital Input: On without a redstone signal, off otherwise"}
TextBox{parent=rs_c_7,x=1,y=6,height=4,text="(Normal) Digital Output: Redstone signal to 'turn it on', none to 'turn it off'\nInverted Digital Output: No redstone signal to 'turn it on', redstone signal to 'turn it off'"}
TextBox{parent=rs_c_7,x=1,y=11,height=2,text="Analog Input: 0-15 redstone power level input\nAnalog Output: 0-15 scaled redstone power level output"}
PushButton{parent=rs_c_7,x=1,y=14,text="\x1b Back",callback=function()rs_pane.set_value(3)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
TextBox{parent=rs_c_8,x=1,y=1,height=5,text="Advanced Options"}
self.rs_cfg_inverted = Checkbox{parent=rs_c_8,x=1,y=3,label="Invert",default=false,box_fg_bg=cpair(colors.red,colors.black),callback=function()end,disable_fg_bg=g_lg_fg_bg}
TextBox{parent=rs_c_8,x=3,y=4,height=4,text="Digital I/O is already inverted (or not) based on intended use. If you have a non-standard setup, you can use this option to avoid needing a redstone inverter.",fg_bg=cpair(colors.gray,colors.lightGray)}
PushButton{parent=rs_c_8,x=1,y=14,text="\x1b Back",callback=function()rs_pane.set_value(3)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg}
--#endregion
--#region Tool Functions
@ -383,9 +402,11 @@ function redstone.create(tool_ctl, main_pane, cfg_sys, rs_cfg, style)
if rsio.is_analog(def.port) then
self.rs_cfg_bundled.set_value(false)
self.rs_cfg_bundled.disable()
self.rs_cfg_advanced.disable()
else
self.rs_cfg_bundled.enable()
self.rs_cfg_bundled.set_value(def.color ~= nil)
self.rs_cfg_advanced.enable()
end
local value = 1
@ -400,6 +421,7 @@ function redstone.create(tool_ctl, main_pane, cfg_sys, rs_cfg, style)
self.rs_cfg_side_l.set_value(tri(rsio.get_io_dir(def.port) == rsio.IO_DIR.IN, "Input Side", "Output Side"))
side.set_value(side_to_idx(def.side))
self.rs_cfg_color.set_value(value)
self.rs_cfg_inverted.set_value(def.invert or false)
rs_pane.set_value(3)
end
@ -418,14 +440,15 @@ function redstone.create(tool_ctl, main_pane, cfg_sys, rs_cfg, style)
local def = tmp_cfg.Redstone[i]
local name = rsio.to_string(def.port)
local io_dir = tri(rsio.get_io_mode(def.port) == rsio.IO_DIR.IN, "\x1a", "\x1b")
local io_dir = tri(rsio.get_io_dir(def.port) == rsio.IO_DIR.IN, "\x1a", "\x1b")
local io_c = tri(rsio.is_digital(def.port), colors.blue, colors.purple)
local conn = def.side
local unit = util.strval(def.unit or "F")
if def.color ~= nil then conn = def.side .. "/" .. rsio.color_name(def.color) end
local entry = Div{parent=rs_list,height=1}
TextBox{parent=entry,x=1,y=1,width=1,text=io_dir,fg_bg=cpair(colors.lightGray,colors.white)}
TextBox{parent=entry,x=1,y=1,width=1,text=io_dir,fg_bg=cpair(tri(def.invert,colors.orange,io_c),colors.white)}
TextBox{parent=entry,x=2,y=1,width=14,text=name}
TextBox{parent=entry,x=16,y=1,width=string.len(conn),text=conn,fg_bg=cpair(colors.gray,colors.white)}
TextBox{parent=entry,x=33,y=1,width=1,text=unit,fg_bg=cpair(colors.gray,colors.white)}
@ -436,7 +459,7 @@ function redstone.create(tool_ctl, main_pane, cfg_sys, rs_cfg, style)
local a = ini_cfg.Redstone[i]
local b = tmp_cfg.Redstone[i]
modified = (a.unit ~= b.unit) or (a.port ~= b.port) or (a.side ~= b.side) or (a.color ~= b.color)
modified = (a.unit ~= b.unit) or (a.port ~= b.port) or (a.side ~= b.side) or (a.color ~= b.color) or (a.invert ~= b.invert)
end
end

View File

@ -35,7 +35,8 @@ local changes = {
{ "v1.7.9", { "ConnTimeout can now have a fractional part" } },
{ "v1.7.15", { "Added front panel UI theme", "Added color accessibility modes" } },
{ "v1.9.2", { "Added standard with black off state color mode", "Added blue indicator color modes" } },
{ "v1.10.2", { "Re-organized peripheral configuration UI, resulting in some input fields being re-ordered" } }
{ "v1.10.2", { "Re-organized peripheral configuration UI, resulting in some input fields being re-ordered" } },
{ "v1.11.8", { "Added advanced option to invert digital redstone signals" } }
}
---@class rtu_configurator
@ -116,6 +117,7 @@ local fields = {
}
-- deep copy peripherals defs
---@param data rtu_peri_definition[]
function tool_ctl.deep_copy_peri(data)
local array = {}
for _, d in ipairs(data) do table.insert(array, { unit = d.unit, index = d.index, name = d.name }) end
@ -123,9 +125,10 @@ function tool_ctl.deep_copy_peri(data)
end
-- deep copy redstone defs
---@param data rtu_rs_definition[]
function tool_ctl.deep_copy_rs(data)
local array = {}
for _, d in ipairs(data) do table.insert(array, { unit = d.unit, port = d.port, side = d.side, color = d.color }) end
for _, d in ipairs(data) do table.insert(array, { unit = d.unit, port = d.port, side = d.side, color = d.color, invert = d.invert }) end
return array
end

View File

@ -33,16 +33,21 @@ function redstone_rtu.new()
-- link digital input
---@param side string
---@param color integer
function public.link_di(side, color)
---@param invert boolean|nil
function public.link_di(side, color, invert)
local f_read ---@type function
if color then
f_read = function ()
return digital_read(rs.testBundledInput(side, color))
if invert then
f_read = function () return digital_read(not rs.testBundledInput(side, color)) end
else
f_read = function () return digital_read(rs.testBundledInput(side, color)) end
end
else
f_read = function ()
return digital_read(rs.getInput(side))
if invert then
f_read = function () return digital_read(not rs.getInput(side)) end
else
f_read = function () return digital_read(rs.getInput(side)) end
end
end
@ -52,36 +57,58 @@ function redstone_rtu.new()
-- link digital output
---@param side string
---@param color integer
function public.link_do(side, color)
---@param invert boolean|nil
function public.link_do(side, color, invert)
local f_read ---@type function
local f_write ---@type function
if color then
f_read = function ()
return digital_read(colors.test(rs.getBundledOutput(side), color))
end
if invert then
f_read = function () return digital_read(not colors.test(rs.getBundledOutput(side), color)) end
f_write = function (level)
if level ~= IO_LVL.FLOATING and level ~= IO_LVL.DISCONNECT then
local output = rs.getBundledOutput(side)
f_write = function (level)
if level ~= IO_LVL.FLOATING and level ~= IO_LVL.DISCONNECT then
local output = rs.getBundledOutput(side)
if digital_write(level) then
output = colors.combine(output, color)
else
output = colors.subtract(output, color)
-- inverted conditions
if digital_write(level) then
output = colors.subtract(output, color)
else output = colors.combine(output, color) end
rs.setBundledOutput(side, output)
end
end
else
f_read = function () return digital_read(colors.test(rs.getBundledOutput(side), color)) end
rs.setBundledOutput(side, output)
f_write = function (level)
if level ~= IO_LVL.FLOATING and level ~= IO_LVL.DISCONNECT then
local output = rs.getBundledOutput(side)
if digital_write(level) then
output = colors.combine(output, color)
else output = colors.subtract(output, color) end
rs.setBundledOutput(side, output)
end
end
end
else
f_read = function ()
return digital_read(rs.getOutput(side))
end
if invert then
f_read = function () return digital_read(not rs.getOutput(side)) end
f_write = function (level)
if level ~= IO_LVL.FLOATING and level ~= IO_LVL.DISCONNECT then
rs.setOutput(side, digital_write(level))
f_write = function (level)
if level ~= IO_LVL.FLOATING and level ~= IO_LVL.DISCONNECT then
rs.setOutput(side, not digital_write(level))
end
end
else
f_read = function () return digital_read(rs.getOutput(side)) end
f_write = function (level)
if level ~= IO_LVL.FLOATING and level ~= IO_LVL.DISCONNECT then
rs.setOutput(side, digital_write(level))
end
end
end
end
@ -92,23 +119,15 @@ function redstone_rtu.new()
-- link analog input
---@param side string
function public.link_ai(side)
unit.connect_input_reg(
function ()
return rs.getAnalogInput(side)
end
)
unit.connect_input_reg(function () return rs.getAnalogInput(side) end)
end
-- link analog output
---@param side string
function public.link_ao(side)
unit.connect_holding_reg(
function ()
return rs.getAnalogOutput(side)
end,
function (value)
rs.setAnalogOutput(side, value)
end
function () return rs.getAnalogOutput(side) end,
function (value) rs.setAnalogOutput(side, value) end
)
end

View File

@ -31,7 +31,7 @@ local sna_rtu = require("rtu.dev.sna_rtu")
local sps_rtu = require("rtu.dev.sps_rtu")
local turbinev_rtu = require("rtu.dev.turbinev_rtu")
local RTU_VERSION = "v1.11.7"
local RTU_VERSION = "v1.11.8"
local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE
local RTU_HW_STATE = databus.RTU_HW_STATE
@ -197,10 +197,10 @@ local function main()
println(message)
log.warning(message)
else
rs_rtu.link_di(entry.side, entry.color)
rs_rtu.link_di(entry.side, entry.color, entry.invert)
end
elseif mode == rsio.IO_MODE.DIGITAL_OUT then
rs_rtu.link_do(entry.side, entry.color)
rs_rtu.link_do(entry.side, entry.color, entry.invert)
elseif mode == rsio.IO_MODE.ANALOG_IN then
-- can't have duplicate inputs
if util.table_contains(capabilities, entry.port) then