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.CommonData; using MECF.Framework.Common.SubstrateTrackings; using System; using System.Collections; using System.Collections.Generic; using Venus_Core; using Venus_RT.Devices.YASKAWA; using Venus_RT.Modules; using Venus_RT.Modules.LPs; namespace Venus_RT.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 RobotMoveInfo _robotMoveInfo = new RobotMoveInfo(); private LidState _CassetteDoor; private LidState _SideDoor; private F_TRIG _bSysVacPressure1 = new F_TRIG(); private F_TRIG _bSysCompressedAirPressure = new F_TRIG(); private R_TRIG _bFlowGaugeSensor = new R_TRIG(); private R_TRIG _bLeakageSensor = new R_TRIG(); private F_TRIG _bDiffPressureSensorSetting1 = new F_TRIG(); private F_TRIG _bDiffPressureSensorSetting2 = new F_TRIG(); private F_TRIG _bIonizerAlarm = new F_TRIG(); private F_TRIG _bFFuAlarm = new F_TRIG(); private F_TRIG _bAreaSensor = new F_TRIG(); private F_TRIG _bModeSwitch = new F_TRIG(); private RD_TRIG _bCassetteDoorTrig = new RD_TRIG(); private RD_TRIG _bSideDoorTrig = new RD_TRIG(); 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"); } } } 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; _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; //if ((EfemEntity.EfemType)SC.GetValue($"EFEM.EfemType") == EfemEntity.EfemType.BrooksEFEM) //{ // BrooksProxy = new BrooksEFEMProxy(); // BrooksProxy.CommandUpdated += MsgOnCommandUpdated; // BrooksProxy.EventUpdated += MsgOnEventUpdated; // BrooksProxy.ErrorOccurred += MsgOnErrorOccurred; //} _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); Action _subscribeLoc = (ModuleName module, int waferCount) => { if (ModuleHelper.IsInstalled(module)) { WaferManager.Instance.SubscribeLocation(module, waferCount); } }; _subscribeLoc(ModuleName.EfemRobot, 2); _subscribeLoc(ModuleName.Aligner1, 1); _subscribeLoc(ModuleName.Aligner2, 1); _subscribeLoc(ModuleName.Cooling1, 1); _subscribeLoc(ModuleName.Cooling2, 1); _subscribeLoc(ModuleName.LP1, SC.GetValue("EFEM.LoadPort.SlotNumber")); _subscribeLoc(ModuleName.LP2, SC.GetValue("EFEM.LoadPort.SlotNumber")); //_subscribeLoc(ModuleName.Flipper, 1); _subscribeLoc(ModuleName.Buffer, 10); DATA.Subscribe("EfemRobot.RobotMoveAction", () => _robotMoveInfo); DATA.Subscribe("LP1.JobDone", () => { return _LPMs[0].JobDone; }); DATA.Subscribe("LP1.NotifyJobDone", () => { if (!_LPMs[0].JobDone || !_LPMs[0].HasCassette) return false; if (SC.GetValue("System.Job.BuzzerTimeWhenJobDone") >= 0 && _LPMs[0].TimerNotifyJobDone.ElapsedMilliseconds > SC.GetValue("System.Job.BuzzerTimeWhenJobDone") * 1000) return false; return _LPMs[0].JobDone; }); DATA.Subscribe("LP2.JobDone", () => { return _LPMs[1].JobDone; }); DATA.Subscribe("LP2.NotifyJobDone", () => { if (!_LPMs[1].JobDone || !_LPMs[1].HasCassette) return false; if (SC.GetValue("System.Job.BuzzerTimeWhenJobDone") >= 0 && _LPMs[1].TimerNotifyJobDone.ElapsedMilliseconds > SC.GetValue("System.Job.BuzzerTimeWhenJobDone") * 1000) return false; return _LPMs[1].JobDone; }); Func _waferSize = (ModuleName module, int slot) => { string sSize = WaferSize.WS12.ToString(); if (ModuleHelper.IsInstalled(module)) { sSize = WaferManager.Instance.GetWafer(module, slot).Size.ToString(); } else { sSize = WaferSize.WS12.ToString(); } return sSize; }; DATA.Subscribe("Aligner1.WaferSize", () => _waferSize(ModuleName.Aligner1, 0)); DATA.Subscribe("Aligner2.WaferSize", () => _waferSize(ModuleName.Aligner2, 0)); DATA.Subscribe("Cooling1.WaferSize", () => _waferSize(ModuleName.Cooling1, 0)); DATA.Subscribe("Cooling2.WaferSize", () => _waferSize(ModuleName.Cooling2, 0)); DATA.Subscribe("EfemRobot.WaferSize", () => _waferSize(ModuleName.EfemRobot, 0)); DATA.Subscribe("Buffer.WaferSize", () => _waferSize(ModuleName.Buffer, 0)); 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 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 void SetRobotMovingInfo(RobotAction action, Hand hand, ModuleName target) { _robotMoveInfo.Action = action; _robotMoveInfo.ArmTarget = hand == Hand.Blade1 ? RobotArm.ArmA : (hand == Hand.Both ? RobotArm.Both : RobotArm.ArmB); _robotMoveInfo.BladeTarget = $"{_robotMoveInfo.ArmTarget}.{target}"; } public bool Pick(MoveParam mp) { 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 (ModuleHelper.IsPm(mp.SrcModule)) { JetPM pM = GetPM(mp.SrcModule); if (pM.IsSlitDoorClosed) { EV.PostAlarmLog(pM.Module.ToString(), "Slit 门必须打开"); return false; } AddAction(new PinAction(mp.SrcModule, pM, MovementPosition.Up, false, mp.Arm, true)); AddAction(new ExtendAction(this, new ExtendParam { Module = mp.SrcModule, Arm = mp.Arm, Pos = ExtendPos.GB })); AddAction(new PinAction(mp.SrcModule, pM, MovementPosition.Down, true, mp.Arm, true)); AddAction(new ExtendAction(this, new ExtendParam { Module = mp.SrcModule, Arm = mp.Arm, Pos = ExtendPos.G4 })); } else { SetRobotMovingInfo(RobotAction.Picking, mp.Arm, mp.SrcModule); AddAction(new PickAction(this, mp)); } return true; } public bool Place(MoveParam mp) { if (ModuleHelper.IsPm(mp.DestModule)) { JetPM pM = GetPM(mp.DestModule); if (pM.IsSlitDoorClosed) { EV.PostAlarmLog(pM.Module.ToString(), "Slit 门必须打开"); return false; } AddAction(new ExtendAction(this, new ExtendParam { Module = mp.DestModule, Arm = mp.Arm, Pos = ExtendPos.PB })); AddAction(new PinAction(mp.DestModule, pM, MovementPosition.Up, true, mp.Arm, false)); AddAction(new ExtendAction(this, new ExtendParam { Module = mp.DestModule, Arm = mp.Arm, Pos = ExtendPos.P4 })); AddAction(new PinAction(mp.DestModule, pM, MovementPosition.Up, false, mp.Arm, false)); } else { SetRobotMovingInfo(RobotAction.Placing, mp.Arm, mp.DestModule); 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); if (pM.IsSlitDoorClosed) { EV.PostAlarmLog(pM.Module.ToString(), "Slit 门必须打开"); return; } AddAction(new PinAction(pickParam.SrcModule, pM, MovementPosition.Up, false, pickParam.Arm, true)); AddAction(new ExtendAction(this, new ExtendParam { Module = pickParam.SrcModule, Arm = pickParam.Arm, Pos = ExtendPos.GB })); AddAction(new PinAction(pickParam.SrcModule, pM, MovementPosition.Down, true, pickParam.Arm, true)); AddAction(new ExtendAction(this, new ExtendParam { Module = pickParam.SrcModule, Arm = pickParam.Arm, Pos = ExtendPos.G4 })); AddAction(new ExtendAction(this, new ExtendParam { Module = placeParam.DestModule, Arm = placeParam.Arm, Pos = ExtendPos.PB })); AddAction(new PinAction(placeParam.DestModule, pM, MovementPosition.Up, true, placeParam.Arm, false)); AddAction(new ExtendAction(this, new ExtendParam { Module = placeParam.DestModule, Arm = placeParam.Arm, Pos = ExtendPos.P4 })); AddAction(new PinAction(placeParam.DestModule, pM, MovementPosition.Up, false, placeParam.Arm, false)); } else { SetRobotMovingInfo(RobotAction.Picking, pickParam.Arm, pickParam.SrcModule); AddAction(new PickAction(this, pickParam)); SetRobotMovingInfo(RobotAction.Placing, placeParam.Arm, placeParam.DestModule); AddAction(new PlaceAction(this, placeParam)); } } public bool Extend(ExtendParam ep) { AddAction(new ExtendAction(this, 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, 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; } _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) { if ((EfemEntity.EfemType)SC.GetValue($"EFEM.EfemType") == EfemEntity.EfemType.BrooksEFEM) return true; AddAction(new LiftAction(this, mod, false)); return true; } public bool Align(ModuleName mod, float delayTime, Aitex.Core.Common.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 _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[15] ? LidState.Close : LidState.Open; // bit 15 // 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 { 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 { 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) { //EV.PostAlarmLog(arg.Module.ToString(), $"NO activated {arg.CommandType} in the queue"); LOG.Write(eEvent.EV_EFEM_COMMON_INFO, Module, $"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.PostMsg(EfemEntity.MSG.LiftActionDone, arg.CommandType); } } else if (ModuleHelper.IsLoadPort(mod)) { Singleton.Instance.EFEM.NotifyLP(mod, LoadportEntity.MSG.ActionDone); } if(arg.CommandType == EfemOperation.Pick || arg.CommandType == EfemOperation.Place) SetRobotMovingInfo(RobotAction.None, Hand.Both, ModuleName.System); action.OnPostWork(arg.Data); LOG.Write(eEvent.EV_EFEM_COMMON_INFO, Module, $"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(eEvent.EV_EFEM_COMMON_INFO, Module, $"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.ActionDone, arg.CommandType); } } else if (ModuleHelper.IsLoadPort(mod)) { Singleton.Instance.EFEM.NotifyLPError(mod ); } LOG.Write(eEvent.EV_EFEM_COMMON_INFO, Module, $"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}]"); } } }