1
0
mirror of https://github.com/metrostroi-repo/MetrostroiAddon.git synced 2026-05-02 00:42:29 +00:00
Files
MetrostroiAddon/lua/metrostroi/systems/sys_ars_mp.lua
2021-01-02 15:32:05 +03:00

301 lines
9.3 KiB
Lua

--------------------------------------------------------------------------------
-- ARS-MP safety system
--------------------------------------------------------------------------------
-- Copyright (C) 2013-2018 Metrostroi Team & FoxWorks Aerospace s.r.o.
-- Contains proprietary code. See license.txt for additional information.
--------------------------------------------------------------------------------
Metrostroi.DefineSystem("ARS_MP")
TRAIN_SYSTEM.DontAccelerateSimulation = false
function TRAIN_SYSTEM:Initialize()
self.Train:LoadSystem("UOS","Relay","Switch", {bass = true})
self.Train:LoadSystem("ALSFreq","Relay","Switch",{bass=true})
self.Train:LoadSystem("AB1","Relay","Switch",{bass=true})
self.Train:LoadSystem("AB2","Relay","Switch",{bass=true})
self.Train:LoadSystem("EPKContacts","Relay","",{close_time = 3})
self.Train:LoadSystem("ROT1","Relay","", { bass = true})
self.Train:LoadSystem("ROT2","Relay","", { bass = true})
self.Train:LoadSystem("EPKC","Relay")
-- Internal state
self.SpeedLimit = 0
self.NextLimit = 0
self.AB = 0
self.AV = 0
self.AV1 = 0
self.ARSRing = 0
self.KRT = 0
self.KRO = 0
self.KRH = 0
--[[ self.Overspeed = false
self.RUVD = false
self.PneumaticBrake1 = false
self.PneumaticBrake2 = true
self.AttentionPedal = false--]]
self.KVT = false
self.LN = 0
self["2"] = 0
self["25"] = 0
self["20"] = 0
self["33G"] = 0
self["33"] = 0
self["17"] = 0
self["8"] = 0
self["44"] = 0
self["48"] = 0
self.EK = 1
self.F6 = 0
self.F5 = 0
self.PrevF5 = 0
self.F4 = 0
self.F3 = 0
self.F2 = 0
self.F1 = 0
self.NoFreq = 0
self.PrevNoFreq = 0
self.ARS = 0
self.AB = 0
self.AV = 0
self.AV1 = 0
self.ABReady = 0
-- Lamps
---self.LKT = false
self.LVD = 0
self.Ring = 0
end
function TRAIN_SYSTEM:Outputs()
return {
--"2","25","20","33G","33","17","8","44","48",
"NoFreq","F1","F2","F3","F4","F5","F6","LN","ARS","AB","KT","LVD","ABReady"
}
end
function TRAIN_SYSTEM:Inputs()
return { "IgnoreThisARS","AttentionPedal","Ring" }
end
function TRAIN_SYSTEM:TriggerInput(name,value)
end
function TRAIN_SYSTEM:Think(dT)
local Train = self.Train
local ALS = Train.ALSCoil
local speed = math.Round(ALS.Speed or 0,1)
local power = self.GE > 0
local TwoToSix = self.Freq > 0
-- ALS, ARS state
if power and not self.EnableARSTimer then
self.EnableARSTimer = CurTime()+1+math.random()*9
elseif not power and self.EnableARSTimer then
self.EnableARSTimer = nil
end
if ALS.Enabled~=self.ALS then
ALS:TriggerInput("Enable",self.ALS)
end
local Power = self.EnableARSTimer and CurTime()-self.EnableARSTimer > 0
local KVT = self.KB > 0
local F1 = ALS.F1*self.ALS
local F2 = ALS.F2*self.ALS
local F3 = ALS.F3*self.ALS
local F4 = ALS.F4*self.ALS
local F5 = ALS.F5*self.ALS
local F6 = ALS.F6*self.ALS
local FreqCount = F1+F2+F3+F4+F5+F6
local TwoFreq = FreqCount==2
if self.AB > 0 then
if FreqCount>0 then self.AB = 0 end
F1 = 1
F2 = 0
F3 = 0
F4 = 0
F5 = 0
F6 = 0
elseif TwoToSix and not TwoFreq then
F1 = 0
F2 = 0
F3 = 0
F4 = math.min(1,F1+F2+F3+F4)
elseif not TwoToSix and TwoFreq then
F1 = 0
F2 = 0
F3 = 0
F4 = 0
F5 = 0
F6 = 0
end
local FreqCode = bit.bor(F1*1,F2*2,F3*4,F4*8,F5*16,F6*32,self.ALS*64,self.GE*128)
if self.FreqCode ~= FreqCode then
if not self.FreqCodeTimer then self.FreqCodeTimer = CurTime() end
if self.FreqCodeTimer and CurTime()-self.FreqCodeTimer>0.8 then
self.FreqCode = FreqCode
self.FreqCodeTimer = nil
self.F1 = F1
self.F2 = F2
self.F3 = F3
self.F4 = F4
self.F5 = F5
self.F6 = F6
self.NoFreq = (1-math.min(1,(self.F1+self.F2+self.F3+self.F4+self.F5+self.F6)))*math.min(1,self.ALS+self.GE)
end
elseif self.FreqCodeTimer then
self.FreqCodeTimer = nil
end
if power or self.ALS > 0 --[[ or self.AB > 0--]] then
local Vlimit = 20
if self.F4 > 0 then Vlimit = 40 end
if self.F3 > 0 then Vlimit = 60 end
if self.F2 > 0 then Vlimit = 70 end
if self.F1 > 0 then Vlimit = 80 end
-- Determine next limit and current limit
self.SpeedLimit = Vlimit
self.NextLimit = Vlimit
if self.F1 > 0 then self.NextLimit = 80 end
if self.F2 > 0 then self.NextLimit = 70 end
if self.F3 > 0 then self.NextLimit = 60 end
if self.F4 > 0 then self.NextLimit = 40 end
if self.F5 > 0 then self.NextLimit = 20 end
if self.F4 > 0 and self.F6 > 0 then
self.NG = true
end
if TwoToSix and self.LN==0 and self.AB==0 then self.SpeedLimit=20 end
if KVT and self.SpeedLimit <= 40 then self.SpeedLimit = 20 end
if KVT and self.SpeedLimit > 40 then self.SpeedLimit = 40 end
else
self.F1 = 0
self.F2 = 0
self.F3 = 0
self.F4 = 0
self.F5 = 0
self.F6 = 0
self.SpeedLimit = 0
self.NextLimit = 0
self.NoFreq = 0
self.FreqCodeTimer = nil
self.FreqCode = 0
end
if Power then
self.ABReady = self.NoFreq*(1-self.AB)
local ABAccept = self.NoFreq--[[ *ALS.Enabled--]] > 0
if ABAccept and not self.ABPressed1 and Train.AB1.Value > 0 then self.ABPressed1 = CurTime() end
if ABAccept and not self.ABPressed2 and Train.AB2.Value > 0 then self.ABPressed2 = CurTime() end
if not ABAccept or Train.AB1.Value == 0 then self.ABPressed1 = nil end
if not ABAccept or Train.AB2.Value == 0 then self.ABPressed2 = nil end
if self.ABPressed1 and self.ABPressed2 and math.abs(self.ABPressed1-self.ABPressed2) < 1 then
self.AB = 1
end
self.ARS = 1-self.AB
local NoFreq = (self.Freq>0 and self.LN==0) or self.NoFreq>0
self.BR2 = KVT and NoFreq and not self.BR1
self.BR1 = KVT and (self.BR1 or not NoFreq) and not self.BR2
local SpeedLimit = self.SpeedLimit
if (speed > SpeedLimit) and not self.RUVD or SpeedLimit<=20 and not (self.BR1 or self.BR2) then
self.RUVD = true
self.RNT = self.RNT or self.KRT==0
elseif speed < SpeedLimit-0.5 and self.RUVD and not self.RNT then
self.RUVD = false
end
if (self.BR1 or self.BR2) and self.RNT then
self.RNT = false
end
if self.RO==true and self.KRH > 0 then
self.RO = CurTime()
end
if self.RO and self.RO~=true and CurTime()-self.RO >7 then
self.RO = false
if speed<5 and not NoFreq then self.ROBrake = true end
end
if self.RO and speed > 5 then self.RO = false end
if self.RO~=true and speed <= 5 and self.KRH == 0 then self.RO = true end
if self.RO and self.BR2 then self.RO = false end
if self.RUVD then
if not self.PN1Timer then self.PN1Timer = CurTime()+3.5-math.max(0,(speed-20))/60*2.5 end
if not self.TW8Timer then self.TW8Timer = self.SpeedLimit<=20 and CurTime()-3 or CurTime() end
end
if not self.RUVD then
if self.PN1Timer then self.PN1Timer = false end
if self.TW8Timer then self.TW8Timer = false end
end
local brake = (self.RUVD or self.ROBrake) and 1 or 0
local pn1 = (self.RO == true or (self.PN1Timer and CurTime()-self.PN1Timer < 0)) and 1 or 0
local pn2 = (self.TW8Timer and CurTime()-self.TW8Timer > 2.7) and 1 or 0
self["33"] = (1-self.LVD)
self["33G"] = brake
self["17"] = (1-self.LVD)
self["2"] = brake*self.KRT
self["20"] = brake
self["25"] = (1-self.LVD)
self["44"] = pn1
self["48"] = pn1
self["8"] = brake*pn2
self.Ring = self.RNT and 1 or 0
local delay = 3.5
if 10 < speed and speed < 30 then delay = 5.5 end
if speed < 3 then delay = 10 end
if (self.RUVD or speed<5 and not NoFreq) and self.KT == 0 then
if not self.EPKTimer then self.EPKTimer = CurTime() end
else
self.EPKTimer = nil
end
if self.EPKTimer and CurTime()-self.EPKTimer > delay then
self.EK = 0
end
self.LVD = math.min(1-self.KRO,self.LVD+brake)
self.LN = self.NG and self.Freq or 0
else
self.BR1 = 0
self.BR2 = 0
self.EK = 1
self.AB = 0
self.ARS = 0
self.LN = 0
self.NG = false
self.ABPressed1 = nil
self.ABPressed2 = nil
self.Ring = 0
self.ROBrake = false
self.LVD = 0
self.ABReady = 0
self.RUVD = true
self.RNT = true
self["33"] = 0
self["33G"] = 0
self["17"] = 0
self["2"] = 0
self["20"] = 0
self["25"] = 0
self["44"] = 0
self["48"] = 0
self["8"] = 0
end
self.EPK = self.GE*self.EK
--Train:WriteTrainWire(90,self.EPK*(1-Train.ARS.Value))
--Train.EPKC:TriggerInput("Set",self.EPK+Train:ReadTrainWire(90))
Train.EPKC:TriggerInput("Set",self.EPK)
end