mirror of
https://github.com/metrostroi-repo/MetrostroiAddon.git
synced 2026-05-02 00:42:29 +00:00
301 lines
9.3 KiB
Lua
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 = (1-self.AB)*(FreqCount*self.ALS == 0 and 1 or 0)
|
|
local ABAccept = self.ABReady > 0 --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
|