using Aitex.Core.Common; using Aitex.Core.Common.DeviceData; using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Device; using Aitex.Core.RT.Event; using Aitex.Core.RT.Log; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using Aitex.Sorter.Common; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using System; using System.Collections; using System.Collections.Generic; using MECF.Framework.Common.CommonData; using VirgoCommon; using VirgoRT.Device; using VirgoRT.Device.YASKAWA; using VirgoRT.Devices.YASKAWA; using VirgoRT.Modules; using VirgoRT.Modules.LPs; namespace VirgoRT.Devices.EFEM { /// /// EFEM object class /// sealed class Efem : EfemBase, IEfem { //---------------------------------Fields---------------------------------------- // private readonly JetPM[] _pm = new JetPM[2]; private readonly Loadport[] _LPMs = new Loadport[2]; private readonly SignalTower _signalT = new SignalTower(); //private readonly CoolingStage[] _aligner = new CoolingStage[2]; //private string _robotMoveAction; private LidState _CassetteDoor; private LidState _SideDoor; private RD_TRIG _bSysVacPressure1 = new RD_TRIG(); //Bit[0] System vacuum source pressure 1 private RD_TRIG _bIonizerCompressedAir = new RD_TRIG(); //Bit[1] Ionizer compressed air private RD_TRIG _bSysCompressedAirPressure = new RD_TRIG(); //Bit[2] System compressed air pressure 1 private RD_TRIG _bFlowGaugeSensor = new RD_TRIG(); //Bit[4] Flow gauge sensor private RD_TRIG _bLeakageSensor = new RD_TRIG(); //Bit[5] Leakage sensor private RD_TRIG _bDiffPressureSensorSetting1 = new RD_TRIG(); //Bit[8] Differential pressure sensor setting 1 private RD_TRIG _bDiffPressureSensorSetting2 = new RD_TRIG(); //Bit[9] Differential pressure sensor setting 2 private RD_TRIG _bIonizerAlarm = new RD_TRIG(); //Bit[10] Ionizer alarm private RD_TRIG _bFFuAlarm = new RD_TRIG(); private RD_TRIG _bAreaSensor = new RD_TRIG(); private RD_TRIG _bModeSwitch = new RD_TRIG(); private RD_TRIG _bCassetteDoorTrig = new RD_TRIG(); private RD_TRIG _bSideDoorTrig = new RD_TRIG(); private RobotMoveInfo _moveInfo; public Dictionary IsBufferPinUp = new Dictionary(); public override ILoadport this[ModuleName mod] { get { if (!ModuleHelper.IsLoadPort(mod)) throw new ApplicationException($"{mod} is NOT Loadport"); return _LPMs[mod - ModuleName.LP1]; } } //---------------------------------Properties------------------------------------ // public LidState CassetteDoor { get => _CassetteDoor; set { _CassetteDoor = value; _bCassetteDoorTrig.CLK = _CassetteDoor == LidState.Close; if (_bCassetteDoorTrig.T) { EV.Notify(CassetteDoorOpen); EV.PostWarningLog(Module.ToString(), "Cassette door opened"); } if (_bCassetteDoorTrig.R) { EV.Notify(CassetteDoorClose); EV.PostInfoLog(Module.ToString(), "Cassette door closed"); } } } public LidState DoorSwitch { get => _SideDoor; set { _SideDoor = value; _bSideDoorTrig.CLK = _SideDoor == LidState.Close; if (_bSideDoorTrig.T) { EV.Notify(EFEMSideDoorOpen); EV.PostAlarmLog(Module.ToString(), "EFEM Side door open"); } if (_bSideDoorTrig.R) { EV.PostInfoLog(Module.ToString(), "EFEM Side door close"); } } } public RobotMoveInfo MoveInfo { get => _moveInfo; set { _moveInfo = value; } } private string CassetteDoorOpen = "CassetteDoorOpen"; private string CassetteDoorClose = "CassetteDoorClose"; private string EFEMSideDoorOpen = "EFEMSideDoorOpen"; private string EFEMVacuumPressureError = "EFEMVacuumPressureError"; private string EFEMCDAError = "EFEMCDAError"; private string EFEMFlowGaugeSensorError = "EFEMFlowGaugeSensorError"; private string EFEMLeakageAlarm = "EFEMLeakageAlarm"; private string EFEMIonizerAlarm = "EFEMIonizerAlarm"; private string EFEMFFUAlarm = "EFEMFFUAlarm"; private string EFEMOffline = "EFEMOffline"; private string EFEMCommunicationError = "EFEMCommunicationError"; private string WaferTransferFailed = "WaferTransferFailed"; private string EFEMError = "EFEMError"; // Constructor // public Efem() { Module = ModuleName.EfemRobot; _moveInfo = new RobotMoveInfo() { Action = RobotAction.Moving, BladeTarget = ModuleName.System.ToString(), }; _pm[0] = DEVICE.GetDevice(ModuleName.PMA.ToString()); _pm[1] = DEVICE.GetDevice(ModuleName.PMB.ToString()); _comm = new EfemComm(); _LPMs[0] = new Loadport(ModuleName.LP1, this); _LPMs[1] = new Loadport(ModuleName.LP2, this); IsBufferPinUp[ModuleName.Aligner1] = false; IsBufferPinUp[ModuleName.Aligner2] = false; IsBufferPinUp[ModuleName.Cooling1] = false; IsBufferPinUp[ModuleName.Cooling2] = false; _msgHandler = new MessageHandler(this); _msgHandler.CommandUpdated += MsgOnCommandUpdated; _msgHandler.EventUpdated += MsgOnEventUpdated; _msgHandler.ErrorOccurred += MsgOnErrorOccurred; CarrierManager.Instance.SubscribeLocation(ModuleName.LP1.ToString(), 1); CarrierManager.Instance.SubscribeLocation(ModuleName.LP2.ToString(), 1); WaferManager.Instance.SubscribeLocation(ModuleName.EfemRobot, 2); WaferManager.Instance.SubscribeLocation(ModuleName.Aligner1, 1); WaferManager.Instance.SubscribeLocation(ModuleName.Aligner2, 1); WaferManager.Instance.SubscribeLocation(ModuleName.Cooling1, 1); WaferManager.Instance.SubscribeLocation(ModuleName.Cooling2, 1); WaferManager.Instance.SubscribeLocation(ModuleName.LP1, 25); WaferManager.Instance.SubscribeLocation(ModuleName.LP2, 25); //DATA.Subscribe("EfemRobot.RobotMoveAction", () => _robotMoveAction); DATA.Subscribe("EfemRobot.RobotMoveInfo", () => _moveInfo); DATA.Subscribe("Aligner1.WaferSize", () => WaferManager.Instance.GetWafer(ModuleName.Aligner1, 0).Size.ToString()); DATA.Subscribe("Aligner2.WaferSize", () => WaferManager.Instance.GetWafer(ModuleName.Aligner2, 0).Size.ToString()); DATA.Subscribe("Cooling1.WaferSize", () => WaferManager.Instance.GetWafer(ModuleName.Cooling1, 0).Size.ToString()); DATA.Subscribe("Cooling2.WaferSize", () => WaferManager.Instance.GetWafer(ModuleName.Cooling2, 0).Size.ToString()); DATA.Subscribe("EfemRobot.WaferSize", () => WaferManager.Instance.GetWafer(ModuleName.EfemRobot, 0).Size.ToString()); DATA.Subscribe("EFEM.CassetteDoor", () => CassetteDoor); DATA.Subscribe("EfemRobot.GripStateBlade1", () => GripStateBlade1); DATA.Subscribe("EfemRobot.GripStateBlade2", () => GripStateBlade2); GripStateBlade1 = "Unknown"; GripStateBlade2 = "Unknown"; _bCassetteDoorTrig.CLK = true; _bSideDoorTrig.CLK = true; EV.Subscribe(new EventItem("Event", CassetteDoorOpen, "Cassette Door Open")); EV.Subscribe(new EventItem("Event", CassetteDoorClose, "Cassette Door Close")); EV.Subscribe(new EventItem("Event", EFEMSideDoorOpen, "EFEM Side Door Open", EventLevel.Alarm, EventType.HostNotification)); EV.Subscribe(new EventItem("Event", EFEMVacuumPressureError, "EFEM Vacuum pressure error", EventLevel.Alarm, EventType.HostNotification)); EV.Subscribe(new EventItem("Event", EFEMCDAError, "EFEM CDA error", EventLevel.Alarm, EventType.HostNotification)); EV.Subscribe(new EventItem("Event", EFEMFlowGaugeSensorError, "EFEM flow gauge sensor error", EventLevel.Alarm, EventType.HostNotification)); EV.Subscribe(new EventItem("Event", EFEMLeakageAlarm, "EFEM leakage alarm", EventLevel.Alarm, EventType.HostNotification)); EV.Subscribe(new EventItem("Event", EFEMIonizerAlarm, "EFEM Ionizer alarm", EventLevel.Alarm, EventType.HostNotification)); EV.Subscribe(new EventItem("Event", EFEMFFUAlarm, "EFEM FFU alarm", EventLevel.Alarm, EventType.HostNotification)); EV.Subscribe(new EventItem("Event", EFEMOffline, "EFEM offline", EventLevel.Alarm, EventType.HostNotification)); EV.Subscribe(new EventItem("Event", EFEMCommunicationError, "EFEM Communication error", EventLevel.Alarm, EventType.HostNotification)); EV.Subscribe(new EventItem("Event", WaferTransferFailed, "Wafer Transfer Failed", EventLevel.Alarm, EventType.HostNotification)); EV.Subscribe(new EventItem("Event", EFEMError, "EFEM Error", EventLevel.Alarm, EventType.HostNotification)); } // Methods // public bool HomeAll() { AddAction(new HomeAllAction(this, ModuleName.EFEM)); AddAction(new OrgshAction(this, ModuleName.EFEM)); AddAction(new TrackAction(this, ModuleName.EFEM)); return true; } public bool Home(ModuleName mod) { AddAction(new HomeModuleAction(this, mod)); return true; } public bool LPReset(ModuleName mod) { AddAction(new LoadPortClearErrorAction(this, mod)); return true; } public bool Load(ModuleName mod) { AddAction(new LoadModuleAction(this, mod)); return true; } public bool Unload(ModuleName mod) { AddAction(new UnloadModuleAction(this, mod)); return true; } public bool ReadCarrierId(ModuleName mod) { AddAction(new ReadCarrierIdModuleAction(this, mod)); return true; } public bool WriteCarrierId(ModuleName mod, string id) { AddAction(new WriteCarrierIdModuleAction(this, mod, id)); return true; } public bool ReadTagData(ModuleName mod) { AddAction(new ReadTagDataModuleAction(this, mod)); return true; } public bool WriteTagData(ModuleName mod, string tagData) { AddAction(new WriteTagDataModuleAction(this, mod, tagData)); return true; } public bool Dock(ModuleName mod) { AddAction(new DockModuleAction(this, mod)); return true; } public bool Undock(ModuleName mod) { AddAction(new UndockModuleAction(this, mod)); return true; } public bool Clamp(ModuleName mod, bool isUnloadClamp) { AddAction(new ClampModuleAction(this, mod, isUnloadClamp)); return true; } public bool Unclamp(ModuleName mod) { AddAction(new UnclampModuleAction(this, mod)); return true; } public bool SetThick(ModuleName mod) { AddAction(new SetThicknessModuleAction(this, mod, "Thick")); return true; } public bool SetThin(ModuleName mod) { AddAction(new SetThicknessModuleAction(this, mod, "Thin")); return true; } public bool ClearError() { AddAction(new ClearErrorAction(this)); return true; } public void AbortRobot() { AddAction(new AbortAction(this)); } public bool Pick(MoveParam mp) { int arm = mp.Arm == Hand.Blade1 ? 0 : 1; var _ws = WaferManager.Instance.GetWafer(mp.DestModule, arm).Size; if (!WaferManager.Instance.CheckWafer(mp.SrcModule, mp.SrcSlot, WaferStatus.Normal)) { EV.PostAlarmLog("System", $"{mp.SrcModule} slot {mp.SrcSlot + 1} wafer is not normal"); return false; } if ((mp.Arm == Hand.Blade1 || mp.Arm == Hand.Both) && !SC.GetValue("EFEM.EfemRobot.LowerBladeEnable")) { EV.PostWarningLog("System", $"Lower Blade 已被禁用"); return false; } if ((mp.Arm == Hand.Blade2 || mp.Arm == Hand.Both) && !SC.GetValue("EFEM.EfemRobot.UpperBladeEnable")) { EV.PostWarningLog("System", $"Upper Blade 已被禁用"); return false; } if (ModuleHelper.IsPm(mp.SrcModule)) { JetPM pM = GetPM(mp.SrcModule); AddAction(new SlitDoorAction(mp.SrcModule, pM, true)); //if (pM.IsSlitDoorClosed) //{ // EV.PostAlarmLog(pM.Module.ToString(), "Slit 门必须打开"); // return false; //} AddAction(new PinAction(mp.SrcModule, pM, MovementPosition.Up, false, mp.Arm, true, false)); AddAction(new ExtendAction(this, pM, new ExtendParam { Module = mp.SrcModule, Arm = mp.Arm, Pos = ExtendPos.GB, ws = _ws })); //_robotMoveAction = string.Format($"{mp.SrcModule}.Picking"); _moveInfo.Action = RobotAction.Picking; _moveInfo.BladeTarget = mp.SrcModule.ToString(); AddAction(new PinAction(mp.SrcModule, pM, MovementPosition.Down, true, mp.Arm, true, true)); AddAction(new ExtendAction(this, pM, new ExtendParam { Module = mp.SrcModule, Arm = mp.Arm, Pos = ExtendPos.G4, ws = _ws })); } else { //_robotMoveAction = string.Format($"{mp.SrcModule}.Picking"); _moveInfo.Action = RobotAction.Picking; _moveInfo.BladeTarget = mp.SrcModule.ToString(); AddAction(new PickAction(this, mp)); } return true; } public bool Place(MoveParam mp) { int arm = mp.Arm == Hand.Blade1 ? 0 : 1; var _ws = WaferManager.Instance.GetWafer(mp.SrcModule, arm).Size; if (mp.Arm == Hand.Blade1 && !SC.GetValue("EFEM.EfemRobot.LowerBladeEnable")) { EV.PostWarningLog("System", $"Lower Blade 已被禁用"); return false; } if (mp.Arm == Hand.Blade2 && !SC.GetValue("EFEM.EfemRobot.UpperBladeEnable")) { EV.PostWarningLog("System", $"Upper Blade 已被禁用"); return false; } if (ModuleHelper.IsPm(mp.DestModule)) { JetPM pM = GetPM(mp.DestModule); AddAction(new SlitDoorAction(mp.DestModule, pM, true)); //if (pM.IsSlitDoorClosed) //{ // EV.PostAlarmLog(pM.Module.ToString(), "Slit 门必须打开"); // return false; //} AddAction(new ExtendAction(this, pM, new ExtendParam { Module = mp.DestModule, Arm = mp.Arm, Pos = ExtendPos.PB, ws = _ws })); //_robotMoveAction = string.Format($"{mp.DestModule}.Placing"); _moveInfo.Action = RobotAction.Placing; _moveInfo.BladeTarget = mp.DestModule.ToString(); AddAction(new PinAction(mp.DestModule, pM, MovementPosition.Up, true, mp.Arm, false, false)); AddAction(new ExtendAction(this, pM, new ExtendParam { Module = mp.DestModule, Arm = mp.Arm, Pos = ExtendPos.P4, ws = _ws })); AddAction(new PinAction(mp.DestModule, pM, MovementPosition.Up, false, mp.Arm, false, true)); } else { //_robotMoveAction = string.Format($"{mp.DestModule}.Placing"); _moveInfo.Action = RobotAction.Placing; _moveInfo.BladeTarget = mp.DestModule.ToString(); AddAction(new PlaceAction(this, mp)); } return true; } public void PickAndPlace(MoveParam pickParam, MoveParam placeParam) { if (!WaferManager.Instance.CheckWafer(pickParam.SrcModule, pickParam.SrcSlot, WaferStatus.Normal)) { EV.PostAlarmLog("System", $"{pickParam.SrcModule} slot {pickParam.SrcSlot + 1} wafer is not normal"); return; } if (ModuleHelper.IsPm(pickParam.SrcModule)) { JetPM pM = GetPM(pickParam.SrcModule); var _ws = WaferManager.Instance.GetWafer(pickParam.SrcModule, 0).Size; AddAction(new SlitDoorAction(pickParam.SrcModule, pM, true)); AddAction(new PinAction(pickParam.SrcModule, pM, MovementPosition.Up, false, pickParam.Arm, true, false)); AddAction(new ExtendAction(this, pM, new ExtendParam { Module = pickParam.SrcModule, Arm = pickParam.Arm, Pos = ExtendPos.GB, ws = _ws })); _moveInfo.Action = RobotAction.Picking; _moveInfo.BladeTarget = pickParam.SrcModule.ToString(); //_robotMoveAction = string.Format($"{pickParam.SrcModule}.Picking"); AddAction(new PinAction(pickParam.SrcModule, pM, MovementPosition.Down, true, pickParam.Arm, true, true)); AddAction(new ExtendAction(this, pM, new ExtendParam { Module = pickParam.SrcModule, Arm = pickParam.Arm, Pos = ExtendPos.G4, ws = _ws })); AddAction(new ExtendAction(this, pM, new ExtendParam { Module = placeParam.DestModule, Arm = placeParam.Arm, Pos = ExtendPos.PB, ws = _ws })); //_robotMoveAction = string.Format($"{placeParam.DestModule}.Placing"); _moveInfo.Action = RobotAction.Placing; _moveInfo.BladeTarget = placeParam.DestModule.ToString(); AddAction(new PinAction(placeParam.DestModule, pM, MovementPosition.Up, true, placeParam.Arm, false, false)); AddAction(new ExtendAction(this, pM, new ExtendParam { Module = placeParam.DestModule, Arm = placeParam.Arm, Pos = ExtendPos.P4, ws = _ws })); AddAction(new PinAction(placeParam.DestModule, pM, MovementPosition.Up, false, placeParam.Arm, false, false)); } else { //_robotMoveAction = string.Format($"{pickParam.SrcModule}.Picking"); _moveInfo.Action = RobotAction.Picking; _moveInfo.BladeTarget = pickParam.SrcModule.ToString(); AddAction(new PickAction(this, pickParam)); //_robotMoveAction = string.Format($"{placeParam.DestModule}.Placing"); _moveInfo.Action = RobotAction.Placing; _moveInfo.BladeTarget = placeParam.DestModule.ToString(); AddAction(new PlaceAction(this, placeParam)); } } public bool Extend(ExtendParam ep) { AddAction(new ExtendAction(this, null, ep)); return true; } public void Goto(MoveParam ep) { //_robotMoveAction = string.Format($"{ep.SrcModule}.Goto"); AddAction(new GotoAction(this, ep)); } public bool Retract(ExtendParam ep) { AddAction(new ExtendAction(this, null, ep)); return true; } public bool Map(ModuleName mod) { if (_LPMs[mod - ModuleName.LP1].Protrusion) { EV.PostAlarmLog(mod.ToString(), $"{mod} wafer protrusion, can not do Map"); return false; } if (SC.GetValue("EFEM.EfemType") == 1) { AddAction(new MapAction(this, mod)); return true; } _LPMs[mod - ModuleName.LP1].Map(); return true; } public bool Grip(Hand blade, bool isGrip) { AddAction(new GripAction(this, blade, isGrip)); return true; } public bool SetPinUp(ModuleName mod) { AddAction(new LiftAction(this, mod, true)); return true; } public bool SetPinDown(ModuleName mod) { AddAction(new LiftAction(this, mod, false)); return true; } public bool Align(ModuleName mod, float delayTime, WaferSize size) { AddAction(new AlignAction(this, mod, size)); return true; } public bool SetLamp(LightType light, LightStatus status) { AddAction(new LedAction(this, light, status)); return true; } public void TurnOffBuzzer() { AddAction(new LedAction(this, LightType.BUZZER1, LightStatus.OFF)); } //public void SwitchOnBuzzerAndRed() //{ // AddAction(new LedAction(this, LightType.RED, LightStatus.ON)); // AddAction(new LedAction(this, LightType.YELLOW, LightStatus.OFF)); // AddAction(new LedAction(this, LightType.GREEN, LightStatus.OFF)); // AddAction(new LedAction(this, LightType.BUZZER1, LightStatus.ON)); //} public override void ReceiveMessage(string sRec) { _msgHandler.ReceiveMessage(sRec); } public override void SetOnline(ModuleName mod, bool online) { this[mod].SetOnline(online); } public override void SetBusy(ModuleName mod, bool busy) { this[mod].Status = DeviceState.Busy; } //--------------------------------Constructor------------------------------------ // private JetPM GetPM(ModuleName mod) { if (!ModuleHelper.IsPm(mod)) throw new ArgumentException("Module argument error"); return _pm[mod - ModuleName.PMA]; } //----------------------------------Private Method------------------------------- // private void MsgOnEventUpdated(object sender, EventArgs e) { if (!(e is EfemEventArgs)) return; EfemEventArgs eArg = e as EfemEventArgs; switch (eArg.CommandType) { case EfemOperation.SigStatus: // EVT:SIGSTAT/Parameter/DATA1/DATA2; string sParam = eArg.DataList[0]; // "SYSTEM" or "Pn" // DATA1 & DATA2 int nData1 = Convert.ToInt32(eArg.DataList[1], 16); int nData2 = Convert.ToInt32(eArg.DataList[2], 16); BitArray baData1 = new BitArray(new int[] { nData1 }); BitArray baData2 = new BitArray(new int[] { nData2 }); if (0 == string.Compare(sParam, Constant.SYS, true)) { // EVT:SIGSTAT/System/00000000/00000004; // DATA1 _bSysVacPressure1.CLK = baData1[0]; // bit 0 _bIonizerCompressedAir.CLK = baData1[1]; // bit 1 _bSysCompressedAirPressure.CLK = baData1[2]; // bit 2 _bFlowGaugeSensor.CLK = baData1[4]; // bit 4 _bLeakageSensor.CLK = baData1[5]; // bit 5 this.DoorSwitch = baData1[6] ? LidState.Close : LidState.Open; // bit 6 //bDrivePower = baData1[7]; // bit 7 _bDiffPressureSensorSetting1.CLK = baData1[8]; // bit 8 _bDiffPressureSensorSetting2.CLK = baData1[9]; // bit 9 _bIonizerAlarm.CLK = baData1[10]; // bit 10 _bFFuAlarm.CLK = baData1[11]; // bit 11 _bAreaSensor.CLK = baData1[12]; // bit 12 _bModeSwitch.CLK = baData1[13]; // bit 13 this.CassetteDoor = baData1[19] ? LidState.Close : LidState.Open; // bit 19 // Post warning and alarm if (!baData1[0]) // Bit[0] ON=Normal, OFF=Abnormal { EV.Notify(EFEMVacuumPressureError); EV.PostAlarmLog(Module.ToString(), "EFEM System vacuum source pressure low"); Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.Error); } if (!baData1[1]) // Bit[1] ON=Normal, OFF=Abnormal { if (!SC.ContainsItem("EFEM.IgnoreIonizerError") || !SC.GetValue("EFEM.IgnoreIonizerError")) { EV.Notify(EFEMIonizerAlarm); EV.PostAlarmLog(Module.ToString(), "EFEM Ionizer compressed air error"); Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.Error); } } if (!baData1[2]) // Bit[2] ON=Normal, OFF=Abnormal { EV.Notify(EFEMCDAError); EV.PostAlarmLog(Module.ToString(), "EFEM System compressed air pressure low"); Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.Error); } if (!baData1[4]) // Bit[4] ON=Normal, OFF=Abnormal { if (!SC.ContainsItem("EFEM.IgnoreWaterFlowError") || !SC.GetValue("EFEM.IgnoreWaterFlowError")) { EV.Notify(EFEMFlowGaugeSensorError); EV.PostAlarmLog(Module.ToString(), "EFEM Flow gauge sensor error"); Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.Error); } } if (!baData1[5]) // Bit[5] ON=Normal, OFF=Abnormal { EV.Notify(EFEMLeakageAlarm); EV.PostAlarmLog(Module.ToString(), "EFEM Leakage alarm"); Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.Error); } if (!baData1[10]) // Bit[10] ON=Normal, OFF=Abnormal { EV.Notify(EFEMIonizerAlarm); EV.PostAlarmLog(Module.ToString(), "EFEM Ionizer alarm"); Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.Error); } if (!baData1[11]) // Bit[11] ON=Normal, OFF=Abnormal { EV.Notify(EFEMFFUAlarm); EV.PostAlarmLog(Module.ToString(), "FFU alarm"); Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.Error); } if (!baData1[13]) // Bit[13] ON=RUN, OFF=Maintain { EV.Notify(EFEMOffline); EV.PostAlarmLog(Module.ToString(), "EFEM switch to Maintain mode, HomeAll to recover"); //Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.ToInit); } // DATA2 _signalT.ChangeLightStatus(LightType.RED, baData2[0] ? LightStatus.ON : baData2[5] ? LightStatus.BLINK : LightStatus.OFF); _signalT.ChangeLightStatus(LightType.GREEN, baData2[1] ? LightStatus.ON : baData2[6] ? LightStatus.BLINK : LightStatus.OFF); _signalT.ChangeLightStatus(LightType.YELLOW, baData2[2] ? LightStatus.ON : baData2[7] ? LightStatus.BLINK : LightStatus.OFF); _signalT.ChangeLightStatus(LightType.BLUE, baData2[3] ? LightStatus.ON : baData2[8] ? LightStatus.BLINK : LightStatus.OFF); _signalT.ChangeLightStatus(LightType.WHITE, baData2[4] ? LightStatus.ON : baData2[9] ? LightStatus.BLINK : LightStatus.OFF); _signalT.ChangeLightStatus(LightType.BUZZER1, baData2[10] ? LightStatus.ON : LightStatus.OFF); /* EFEM 程序中目前没有实现 _RobotErr.CLK = baData2[27]; // bit 27 bool bArmNotExtendLLA = baData2[30]; // bit 30 bool bArmNotExtendLLB = baData2[31]; // bit 31 */ } // system event else { _LPMs[eArg.Module - ModuleName.LP1].HandleEvent(eArg); } // FOUP EVENT break; case EfemOperation.GetWaferInfo: _LPMs[eArg.Module - ModuleName.LP1].HandleEvent(eArg); break; default: break; } } private void MsgOnCommandUpdated(object sender, EventArgs e) { EfemActionArgs arg = e as EfemActionArgs; if (arg == null) throw new ArgumentNullException("Argument is Null"); if (arg.CommandType == EfemOperation.Ready) { this.CommunicationConnected = true; Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.CommReady); return; } EfemActionBase action = null; lock (_lockerAction) { foreach (var item in _actions) { if (item is EfemActionBase a1) { if (a1.Type == arg.CommandType && item.Status != ActionStatus.Completed) { action = a1; break; } } } if (action == null) { LOG.Write($"NO activated [{arg.ID}] [{arg.CommandType}] in the queue"); return; } // 更新 action 状态 action.Status = arg.Status; if (arg.Status == ActionStatus.Completed) { ModuleName mod = action.Module; // Map 命令比较特别, module 是LPX但是用robot做mapping if (mod == ModuleName.EFEM || mod == ModuleName.EfemRobot || ModuleHelper.IsAligner(mod) || ModuleHelper.IsCooling(mod) || arg.CommandType == EfemOperation.Map) { if ((action.Type != EfemOperation.Light) && (action.Type != EfemOperation.Lift)) { Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.ActionDone, arg.CommandType); } if (action.Type == EfemOperation.Lift) { Singleton.Instance.EFEM.SetLiftDownDone(); } } else if (ModuleHelper.IsLoadPort(mod)) { Singleton.Instance.EFEM.NotifyLP(mod, LoadPortModule.MSG.ActionDone); } //_robotMoveAction = string.Format($"System.None"); //_moveInfo.Action = RobotAction.None; action.OnPostWork(arg.Data); LOG.Write($"efem action [{action.GetType().Name}] [{action.ID}][{action.Type}] removed from queue"); _actions.Remove(action); } } } private void MsgOnErrorOccurred(object sender, EventArgs e) { if (!(e is EfemErrorArgs arg)) return; this.Status = DeviceState.Error; EfemActionBase action = null; lock (_lockerAction) { foreach (var item in _actions) { if (item is EfemActionBase a1) { if (a1.Type == arg.CommandType && item.Status != ActionStatus.Completed) { action = a1; break; } } } if (action == null) { LOG.Write($"NO activated [{arg.ID}] [{arg.Module}] [{arg.CommandType}] in the queue"); return; } ModuleName mod = action.Module; if (mod == ModuleName.EFEM || mod == ModuleName.EfemRobot || ModuleHelper.IsAligner(mod) || ModuleHelper.IsCooling(mod) || arg.CommandType == EfemOperation.Map) { if (action.Type != EfemOperation.Light) { Singleton.Instance.EFEM.PostMsg(EfemEntity.MSG.Error); } } else if (ModuleHelper.IsLoadPort(mod)) { Singleton.Instance.EFEM.NotifyLPError(mod); } LOG.Write($"efem action [{action.GetType().Name}] [{action.ID}][{action.Module}][{action.Type}] removed from queue"); _actions.Remove(action); } EV.Notify(EFEMError); EV.PostAlarmLog(Module.ToString(), $"{arg.Description}, [{arg.Message}], [{arg.Factor}]"); } } }