using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml; using Aitex.Core.Common.DeviceData; using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Device; using Aitex.Core.RT.Event; using Aitex.Core.RT.IOCore; using Aitex.Core.RT.Log; using Aitex.Core.RT.OperationCenter; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; namespace Aitex.Core.RT.Device.Unit { public enum SignalType { Acitvie, Passive, } public enum SignalID { CS_0, CS_1, AM_AVBL, VALID, TR_REQ, BUSY, COMPT, CONT, L_REQ, U_REQ, HO_AVBL, READY, ES } public class Signal { public bool Value { get { if (_di != null) return _di.Value; if (_do != null) return _do.Value; return false; } } private SignalID _id; private RD_TRIG _trig = new RD_TRIG(); private DIAccessor _di = null; private DOAccessor _do = null; public event Action OnChanged; public Signal(SignalID id, DIAccessor diAccessor, DOAccessor doAccessor) { _id = id; _di = diAccessor; _do = doAccessor; } public void Monitor() { if (_di != null) _trig.CLK = _di.Value; if (_do != null) _trig.CLK = _do.Value; if (_trig.R) { if (OnChanged != null) OnChanged(_id, true); } if (_trig.M) { if (OnChanged != null) OnChanged(_id, false); } } public void Reset() { _trig.RST = true; } } public enum LPAccessMode { Operator = 0, AMHS = 1, }; public enum LPTransferState { OutOfService = 0, TransferBlocked = 1, ReadyToLoad = 2, ReadyToUnload = 3, InService = 4, TransferReady = 5, } public interface IE84Provider { bool ReadyForLoad(); bool ReadyForUnload(); bool FoupArrirved(); bool FoupRemoved(); } public class E84Passiver : BaseDevice, IDevice { public enum E84State { Idle, WaitForTrReqOn, WaitForBusyOn, WaitForTransfer, WaitForBusyOff, WaitForValidOff, Error, } public enum Timeout { TP1, TP2, TP3, TP4, TP5, } public bool LightCurtainBroken { get; set; } //interlock public LPAccessMode Mode{ get; set; } public LPTransferState TransferState { get; set; } public IE84Provider Provider { get; set; } //Active equipment signal private DIAccessor _diValid; private DIAccessor _diCS0; private DIAccessor _diCS1; private DIAccessor _diAmAvbl; private DIAccessor _diTrReq; private DIAccessor _diBusy; private DIAccessor _diCompt; private DIAccessor _diCont; //Passive private DOAccessor _doLoadReq; private DOAccessor _doUnloadReq; private DOAccessor _doReady; private DOAccessor _doHOAvbl; private DOAccessor _doES; private DeviceTimer _timer = new DeviceTimer(); private R_TRIG _trigReset = new R_TRIG(); private List _signals = new List(); //timeout private SCConfigItem _scTimeoutTP1; private SCConfigItem _scTimeoutTP2; private SCConfigItem _scTimeoutTP3; private SCConfigItem _scTimeoutTP4; private SCConfigItem _scTimeoutTP5; private int reqOnTimeout = 2; //L_REQ|U_REQ_ON ON ---> TR REQ ON private int readyOnTimeout = 2; //READY ON ---> BUSY ON private int busyOnTimeout = 2; //BUSYON -- CARRIAGE DETECT|CARRIAGE REMOVE private int reqOffTimeout = 2; //L_REQ|U_REQ off --->BUSY off private int readyOffTimeout = 2; //Ready off --->Valid off private E84State _state; private Timeout _tp; public E84Passiver(string module, XmlElement node, string ioModule = "") { base.Module = node.GetAttribute("module"); base.Name = node.GetAttribute("id"); base.Display = node.GetAttribute("display"); base.DeviceID = node.GetAttribute("schematicId"); _diValid = ParseDiNode("VALID", node, ioModule); _signals.Add(new Signal(SignalID.VALID, _diValid, null)); _diCS0 = ParseDiNode("CS_0", node, ioModule); _signals.Add(new Signal(SignalID.CS_0, _diCS0, null)); _diCS1 = ParseDiNode("CS_1", node, ioModule); _signals.Add(new Signal(SignalID.CS_1, _diCS1, null)); _diAmAvbl = ParseDiNode("AM_AVBL", node, ioModule); _signals.Add(new Signal(SignalID.AM_AVBL, _diAmAvbl, null)); _diTrReq = ParseDiNode("TR_REQ", node, ioModule); _signals.Add(new Signal(SignalID.TR_REQ, _diTrReq, null)); _diBusy = ParseDiNode("BUSY", node, ioModule); _signals.Add(new Signal(SignalID.BUSY, _diBusy, null)); _diCompt = ParseDiNode("COMPT", node, ioModule); _signals.Add(new Signal(SignalID.COMPT, _diCompt, null)); _diCont = ParseDiNode("CONT", node, ioModule); _signals.Add(new Signal(SignalID.CONT, _diCont, null)); _doLoadReq = ParseDoNode("L_REQ", node, ioModule); _signals.Add(new Signal(SignalID.L_REQ, null, _doLoadReq)); _doUnloadReq = ParseDoNode("U_REQ", node, ioModule); _signals.Add(new Signal(SignalID.U_REQ, null, _doUnloadReq)); _doReady = ParseDoNode("READY", node, ioModule); _signals.Add(new Signal(SignalID.READY, null, _doReady)); _doHOAvbl = ParseDoNode("HO_AVBL", node, ioModule); _signals.Add(new Signal(SignalID.HO_AVBL, null, _doHOAvbl)); _doES = ParseDoNode("ES", node, ioModule); _signals.Add(new Signal(SignalID.ES, null, _doES)); foreach (var signal in _signals) { signal.OnChanged += OnSignalChange; } _scTimeoutTP1 = SC.GetConfigItem("Fa.E84.TP1"); _scTimeoutTP2 = SC.GetConfigItem("Fa.E84.TP2"); _scTimeoutTP3 = SC.GetConfigItem("Fa.E84.TP3"); _scTimeoutTP4 = SC.GetConfigItem("Fa.E84.TP4"); _scTimeoutTP5 = SC.GetConfigItem("Fa.E84.TP5"); } public bool Initialize() { reset(); return true; } private bool InvokeReset(string arg1, object[] arg2) { //string reason; EV.PostInfoLog(Module, $"E84 reset {Module}.{Name}"); reset(); return true; } public void Terminate() { reset(); } private void reset() { _doLoadReq.Value = false; _doUnloadReq.Value = false; _doReady.Value = false; _doHOAvbl.Value = false; _doES.Value = false; _state = E84State.Idle; foreach (var signal in _signals) { signal.Reset(); } } public void Monitor() { try { foreach (var signal in _signals) { signal.Monitor(); } if (LightCurtainBroken) { _doES.Value = false; } else { _doES.Value = true; } if (Mode != LPAccessMode.AMHS) { _doHOAvbl.Value = false; return; } if (_timer.IsTimeout()) { _doHOAvbl.Value = false; _doLoadReq.Value = false; _doUnloadReq.Value = false; _doReady.Value = false; _doES.Value = false; _state = E84State.Error; switch (_state) { case E84State.WaitForTrReqOn: _tp = Timeout.TP1; break; case E84State.WaitForBusyOn: _tp = Timeout.TP2; break; case E84State.WaitForTransfer: _tp = Timeout.TP3; break; case E84State.WaitForBusyOff: _tp = Timeout.TP4; break; case E84State.WaitForValidOff: _tp = Timeout.TP5; break; } EV.PostMessage("E84", EventEnum.DefaultAlarm, string.Format("E84 {0} Timeout", _tp)); } switch (_state) { case E84State.Idle: { if (waitValidOn()) { _state = E84State.WaitForTrReqOn; if (_scTimeoutTP1 != null) reqOnTimeout = _scTimeoutTP1.IntValue; _timer.Start(reqOnTimeout); } } break; case E84State.WaitForTrReqOn: { if (wait4TrReqOn()) { _state = E84State.WaitForBusyOn; if(_scTimeoutTP2!= null) readyOnTimeout = _scTimeoutTP2.IntValue; _timer.Start(readyOnTimeout); } } break; case E84State.WaitForBusyOn: { if (wait4BusyOn()) { _state = E84State.WaitForTransfer; if (_scTimeoutTP3 != null) busyOnTimeout = _scTimeoutTP3.IntValue; _timer.Start(busyOnTimeout); } } break; case E84State.WaitForTransfer: { if (wait4Transfer()) { _state = E84State.WaitForBusyOff; if (_scTimeoutTP4 != null) reqOffTimeout = _scTimeoutTP4.IntValue; _timer.Start(reqOffTimeout); } } break; case E84State.WaitForBusyOff: { if (wait4BusyOff()) { _state = E84State.WaitForValidOff; if (_scTimeoutTP5 != null) readyOffTimeout = _scTimeoutTP5.IntValue; _timer.Start(readyOffTimeout); } } break; case E84State.WaitForValidOff: { if (waitValidOff()) { _state = E84State.Idle; _timer.Stop(); } } break; case E84State.Error: { if (autoRecovery()) { _state = E84State.Idle; _timer.Stop(); } } break; } } catch (Exception ex) { LOG.Write(ex); } } public void Reset() { _doLoadReq.Value = false; _doUnloadReq.Value = false; _doReady.Value = false; _doHOAvbl.Value = false; _doES.Value = false; foreach (var signal in _signals) { signal.Reset(); } if (TransferState != LPTransferState.OutOfService) { if (Mode == LPAccessMode.AMHS) { _doHOAvbl.Value = true; _doES.Value = true; } } } private bool waitValidOn() { if (_diValid.Value) { if (!_diCS0.Value && !_diCS1.Value) { EV.PostMessage("E84", EventEnum.DefaultWarning, "When VALID turn on, CS0 or CS1 should be on"); _doHOAvbl.Value = false; return false; } if (_diTrReq.Value) { EV.PostMessage("E84", EventEnum.DefaultWarning, "When VALID turn on, VALID should be off"); _doHOAvbl.Value = false; return false; } if (_diBusy.Value) { EV.PostMessage("E84", EventEnum.DefaultWarning, "When VALID turn on, BUSY should be off"); _doHOAvbl.Value = false; return false; } if (_diCompt.Value) { EV.PostMessage("E84", EventEnum.DefaultWarning, "When VALID turn on, COMPT should be off"); _doHOAvbl.Value = false; return false; } if (TransferState == LPTransferState.ReadyToLoad) { _doLoadReq.Value = true; } else if (TransferState == LPTransferState.ReadyToUnload) { _doUnloadReq.Value = true; } } return true; } private bool wait4TrReqOn() { if (_diTrReq.Value) { if (!_diCS0.Value && !_diCS1.Value) { EV.PostMessage("E84", EventEnum.DefaultWarning, "When TR_REQ turn on, CS0 or CS1 should be on"); _doHOAvbl.Value = false; return false; } if (!_diValid.Value) { EV.PostMessage("E84", EventEnum.DefaultWarning, "When TR_REQ turn on, TR_REQ should be off"); _doHOAvbl.Value = false; return false; } if (_diBusy.Value) { EV.PostMessage("E84", EventEnum.DefaultWarning, "When TR_REQ turn on, BUSY should be off"); _doHOAvbl.Value = false; return false; } if (_diCompt.Value) { EV.PostMessage("E84", EventEnum.DefaultWarning, "When TR_REQ turn on, COMPT should be off"); _doHOAvbl.Value = false; return false; } if (TransferState == LPTransferState.ReadyToLoad) { if(Provider.ReadyForLoad()) _doReady.Value = true; } else if (TransferState == LPTransferState.ReadyToUnload) { if(Provider.ReadyForUnload()) _doReady.Value = true; } return true; } return false; } private bool wait4BusyOn() { if (_diBusy.Value) { if (!_diCS0.Value && !_diCS1.Value) { EV.PostMessage("E84", EventEnum.DefaultWarning, "When BUSY turn on, CS0 or CS1 should be on"); _doHOAvbl.Value = false; return false; } if (!_diValid.Value) { EV.PostMessage("E84", EventEnum.DefaultWarning, "When BUSY turn on, VALID should be on"); _doHOAvbl.Value = false; return false; } if (!_diTrReq.Value) { EV.PostMessage("E84", EventEnum.DefaultWarning, "When TR_REQ turn on, TR_REQ should be on"); _doHOAvbl.Value = false; return false; } if (_diCompt.Value) { EV.PostMessage("E84", EventEnum.DefaultWarning, "When TR_REQ turn on, COMPT should be off"); _doHOAvbl.Value = false; return false; } return true; } return false; } private bool wait4Transfer() { if (TransferState == LPTransferState.ReadyToLoad) { if (Provider.FoupArrirved()) //FOUP placement { _doLoadReq.Value = false; return true; } } else if (TransferState == LPTransferState.ReadyToUnload) { if (Provider.FoupArrirved()) //FOUP placement { _doUnloadReq.Value = false; return true; } } return false; } private bool wait4BusyOff() { if (_diCompt.Value && !_diTrReq.Value && !_diBusy.Value) { if (!_diValid.Value) { EV.PostMessage("E84", EventEnum.DefaultWarning, "When BUSY turn off, VALID should be on"); _doHOAvbl.Value = false; return false; } if (!_diCS0.Value && !_diCS1.Value) { EV.PostMessage("E84", EventEnum.DefaultWarning, "When BUSY turn off, CS0 or CS1 should be on"); _doHOAvbl.Value = false; return false; } _doReady.Value = false; return true; } return false; } private bool waitValidOff() { if (_diValid.Value && (_diCS0.Value || _diCS1.Value) && !_diCompt.Value) { _doHOAvbl.Value = true; if (_diBusy.Value) { EV.PostMessage("E84", EventEnum.DefaultWarning, "When VALID turn off, BUSY should be off"); _doHOAvbl.Value = false; return false; } if (_diTrReq.Value) { EV.PostMessage("E84", EventEnum.DefaultWarning, "When VALID turn off, TR REQ should be off"); _doHOAvbl.Value = false; return false; } _doLoadReq.Value = false; _doUnloadReq.Value = false; _doReady.Value = false; _doES.Value = false; return true; } return false; } private bool autoRecovery() { bool ret = false; switch (_tp) { case Timeout.TP1: case Timeout.TP2: case Timeout.TP5: { if ( !_diAmAvbl.Value && !_diValid.Value && !_diCS0.Value && !_diCS1.Value &&!_diTrReq.Value && !_diBusy.Value && !_diCompt.Value && !_diCont.Value) ret = true; } break; } return ret; } private void OnSignalChange(SignalID signal, bool value) { } } }