using System; using System.Diagnostics; using System.Linq; using Aitex.Core.Common; using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Device; using Aitex.Core.RT.Event; using Aitex.Core.RT.Fsm; using Aitex.Core.RT.Log; using Aitex.Core.RT.OperationCenter; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using Aitex.Core.Utilities; using Aitex.Sorter.Common; using FurnaceRT.Equipments.PMs; using FurnaceRT.Equipments.Systems; using MECF.Framework.Common.Alarms; using MECF.Framework.Common.Device.Bases; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Event; using MECF.Framework.Common.Schedulers; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robot; namespace FurnaceRT.Equipments.CarrierRobots { public partial class CarrierRobotModule : CarrierRobotModuleBase, IE87CallBack { public enum STATE { Init, Idle, Error, Homing, InTransfer, Loading, Unloading, Picking, Placing, Gotoing, Transfer, CycleSwaping, } public enum MSG { Home, Reset, Init, Error, Abort, InTransfer, TransferComplete, Load, LoadRetry, Unload, UnloadRetry, Pick, PickRetry, Place, PlaceRetry, Goto, GotoRetry, SwapRetry, Transfer, CycleSwap } public override bool IsReady { get { return FsmState == (int)STATE.Idle; } } public override bool IsError { get { return FsmState == (int)STATE.Error; } } public override bool IsInit { get { return FsmState == (int)STATE.Init; } } public event Action OnEnterError; private bool _jobDone; private bool _isInit; private Stopwatch _timerNotifyJobDone = new Stopwatch(); private CarrierLoad _loadRoutine; private CarrierUnload _unloadRoutine; private CarrierRobotHome _home; private CarrierRobotPick _pick; private CarrierRobotPlace _place; private CarrierRobotGoto _goto; private CarrierRobotSwap _swap; private CarrierRobotCycleSwap _cycleSwap; private bool _uiFoupSensor; public bool IsExcuteRoutineFailed { get; set; } public CarrierRobotModule(ModuleName module) : base() { Name = module.ToString(); Module = module.ToString(); IsOnline = true; } public override bool Initialize() { InitRoutine(); InitDevice(); InitFsm(); InitOp(); InitData(); InitAlarmDefine(); Singleton.Instance.OnAlarmEvent += Instance_OnAlarmEvent; return base.Initialize(); } private void Instance_OnAlarmEvent(EventItem item) { if (item != null && item.Level == EventLevel.Alarm && (item.Source == Name || item.Source == Module)) { DEVICE.GetDevice("System.SignalTower")?.Reset(); LOG.Write($"{item.Source} {item.EventEnum} {item.Description}\n"); PostMsg(MSG.Error); } } private void InitRoutine() { _loadRoutine = new CarrierLoad(this); _unloadRoutine = new CarrierUnload(this); _home = new CarrierRobotHome(this); _pick = new CarrierRobotPick(this); _place = new CarrierRobotPlace(this); _swap = new CarrierRobotSwap(this); _cycleSwap = new CarrierRobotCycleSwap(this); } private void InitData() { DATA.Subscribe($"{Module}.Status", () => IsExcuteRoutineFailed ? STATE.Error.ToString() : StringFsmStatus); DATA.Subscribe($"{Module}.IsOnline", () => IsOnline); DATA.Subscribe($"{Module}.IsError", () => IsError); DATA.Subscribe($"{Module}.SwapCycledCount", () => _swap.LoopCounter); DATA.Subscribe($"{Module}.CycleSwapCycledCount", () => _cycleSwap._overAllLoopCount); } private void InitOp() { OP.Subscribe($"{Module}.Home", (string cmd, object[] args) => CheckToPostMessage((int)MSG.Home)); OP.Subscribe($"{Module}.Abort", (string cmd, object[] args) => CheckToPostMessage((int)MSG.Abort)); OP.Subscribe($"{Module}.Reset", (string cmd, object[] args) => CheckToPostMessage((int)MSG.Reset)); OP.Subscribe($"{Module}.Pick", (string cmd, object[] args) => CheckToPostMessage((int)MSG.Pick, args)); OP.Subscribe($"{Module}.Place", (string cmd, object[] args) => CheckToPostMessage((int)MSG.Place, args)); OP.Subscribe($"{Module}.Transfer", (string cmd, object[] args) => CheckToPostMessage((int)MSG.Transfer, args)); OP.Subscribe($"{Module}.CycleSwap", (string cmd, object[] args) => CheckToPostMessage((int)MSG.CycleSwap, args)); OP.Subscribe($"{Module}.Load", (string cmd, object[] args) => CheckToPostMessage((int)MSG.Load)); OP.Subscribe($"{Module}.Unload", (string cmd, object[] args) => CheckToPostMessage((int)MSG.Unload)); OP.Subscribe($"{Module}.In", (string cmd, object[] args) => { return true; }); OP.Subscribe($"{Module}.Out", (string cmd, object[] args) => { return true; }); OP.Subscribe($"{Module}.AlarmAction", (string cmd, object[] args) => { Enum.TryParse(args[0].ToString(), out AlarmAction alarmAction); string eventName = null; if (args.Length > 1) eventName = args[1].ToString(); if (eventName != null) { EV.ClearAlarmEvent(eventName); var item = _triggeredAlarmList.FirstOrDefault(x => x.EventEnum == eventName); if (item != null) { item.Reset(); _triggeredAlarmList.Remove(item); } if (item != null) { switch (alarmAction) { case AlarmAction.Retry: { CheckToPostMessage((int)item.RetryMessage, item.RetryMessageParas); } break; case AlarmAction.Abort: { CheckToPostMessage((int)MSG.Abort); } break; case AlarmAction.Clear: { int alarmCount = 0; var alarms = EV.GetAlarmEvent(); foreach (var alarm in alarms) { if (alarm.Level == EventLevel.Alarm && alarm.Source == Name) alarmCount++; } if (alarmCount == 0) CheckToPostMessage((int)MSG.Reset); } break; case AlarmAction.Continue: { int alarmCount = 0; var alarms = EV.GetAlarmEvent(); foreach (var alarm in alarms) { if (alarm.Level == EventLevel.Alarm && alarm.Source == Name) alarmCount++; } if (alarmCount == 0) CheckToPostMessage((int)MSG.Reset); } break; } } } return true; }); OP.Subscribe($"{Module}.SetOnline", (string cmd, object[] args) => { IsOnline = true; return true; }); OP.Subscribe($"{Module}.SetOffline", (string cmd, object[] args) => { IsOnline = false; return true; }); } private void InitFsm() { EnumLoop.ForEach((item) => { MapState((int)item, item.ToString()); }); EnumLoop.ForEach((item) => { MapMessage((int)item, item.ToString()); }); EnableFsm(50, STATE.Init); //Init Transition(STATE.Init, MSG.Home, FsmStartHome, STATE.Homing); Transition(STATE.Error, MSG.Home, FsmStartHome, STATE.Homing); Transition(STATE.Idle, MSG.Home, FsmStartHome, STATE.Homing); Transition(STATE.Homing, FSM_MSG.TIMER, FsmMonitorHomeTask, STATE.Idle); Transition(STATE.Homing, MSG.Error, null, STATE.Init); Transition(STATE.Homing, MSG.Abort, FsmAbortTask, STATE.Init); EnterExitTransition(STATE.Idle, FsmEnterIdle, FSM_MSG.NONE, FsmExitIdle); Transition(STATE.Idle, MSG.Abort, null, STATE.Idle); Transition(STATE.Idle, MSG.Reset, null, STATE.Idle); Transition(STATE.Init, MSG.Reset, null, STATE.Init); Transition(STATE.Error, MSG.Abort, FsmAbortTask, STATE.Error); //Error AnyStateTransition(MSG.Error, FsmOnError, STATE.Error); Transition(STATE.Error, MSG.Reset, FsmReset, STATE.Idle); EnterExitTransition(STATE.Error, FsmEnterError, FSM_MSG.NONE, FsmExitError); //load Transition(STATE.Error, MSG.LoadRetry, FsmStartLoad, STATE.Loading); Transition(STATE.Idle, MSG.Load, FsmStartLoad, STATE.Loading); Transition(STATE.Loading, FSM_MSG.TIMER, FsmMonitorLoadTask, STATE.Idle); Transition(STATE.Loading, MSG.Abort, FsmAbortTask, STATE.Idle); //unload Transition(STATE.Error, MSG.UnloadRetry, FsmStartUnload, STATE.Unloading); Transition(STATE.Idle, MSG.Unload, FsmStartUnload, STATE.Unloading); Transition(STATE.Unloading, FSM_MSG.TIMER, FsmMonitorUnloadTask, STATE.Idle); Transition(STATE.Unloading, MSG.Abort, FsmAbortTask, STATE.Idle); //pick Transition(STATE.Error, MSG.PickRetry, FsmStartPick, STATE.Picking); Transition(STATE.Idle, MSG.Pick, FsmStartPick, STATE.Picking); Transition(STATE.Picking, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.Picking, MSG.Abort, FsmAbortTask, STATE.Idle); //place Transition(STATE.Error, MSG.PlaceRetry, FsmStartPlace, STATE.Placing); Transition(STATE.Idle, MSG.Place, FsmStartPlace, STATE.Placing); Transition(STATE.Placing, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.Placing, MSG.Abort, FsmAbortTask, STATE.Idle); //goto Transition(STATE.Error, MSG.GotoRetry, FsmStartGoto, STATE.Gotoing); Transition(STATE.Idle, MSG.Goto, FsmStartGoto, STATE.Gotoing); Transition(STATE.Gotoing, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.Gotoing, MSG.Abort, FsmAbortTask, STATE.Idle); //swap Transition(STATE.Idle, MSG.Transfer, FsmStartSwap, STATE.Transfer); Transition(STATE.Transfer, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.Transfer, MSG.Abort, FsmAbortTask, STATE.Idle); //CycleSwap Transition(STATE.Idle, MSG.CycleSwap, FsmStartCycleSwap, STATE.CycleSwaping); Transition(STATE.CycleSwaping, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.CycleSwaping, MSG.Abort, FsmAbortTask, STATE.Idle); } public override bool Home(out string reason) { if (!CheckToPostMessage((int)MSG.Home)) { reason = $"Can not home in {StringFsmStatus} status"; return false; } reason = string.Empty; return true; } public override void NoteJobStart() { _jobDone = false; } public override void NoteJobComplete() { _timerNotifyJobDone.Restart(); _jobDone = true; } public override void Monitor() { base.Monitor(); _alarmSignaRobotAlarmTrig.CLK = _alarmSignaRobotAlarm.Value; if (_alarmSignaRobotAlarmTrig.Q) { RobotDIAlarm.Set(); CarrierRobotDevice.NoteError(""); } if (SC.GetValue("System.IsSimulatorMode")) { var hasFoupSensor = !CarrierManager.Instance.CheckNoCarrier(ModuleName.CarrierRobot, 0); var carrierRobotFoupInfo = CarrierManager.Instance.GetCarrier(ModuleName.CarrierRobot); if (hasFoupSensor && carrierRobotFoupInfo != null) { carrierRobotFoupInfo.UICarrierStatusEnum = CarrierStatus.TRAKCST; carrierRobotFoupInfo.UICarrierType = carrierRobotFoupInfo.CarrierType.ToString(); _uiFoupSensor = true; var pmModule = Singleton.Instance.Modules[ModuleName.PM1] as PMModule; carrierRobotFoupInfo.UICarrierColor = pmModule.GetCarrierUIColor(carrierRobotFoupInfo.UICarrierType, carrierRobotFoupInfo.UICarrierStatusEnum); } Singleton.Instance.SetUIWaferCount(carrierRobotFoupInfo, ModuleName.CarrierRobot, out var wafers); Singleton.Instance.SetVisibility(carrierRobotFoupInfo, hasFoupSensor); } else { var hasFoupSensor = CarrierRobotDevice.IsWaferPresenceOnBlade1 || !CarrierManager.Instance.CheckNoCarrier(ModuleName.CarrierRobot, 0); var carrierRobotFoupInfo = CarrierManager.Instance.GetCarrier(ModuleName.CarrierRobot); if (hasFoupSensor && carrierRobotFoupInfo != null) { _uiFoupSensor = true; carrierRobotFoupInfo.UICarrierType = carrierRobotFoupInfo.CarrierType.ToString(); carrierRobotFoupInfo.UICarrierStatusEnum = CarrierStatus.TRAKCST; var pmModule = Singleton.Instance.Modules[ModuleName.PM1] as PMModule; carrierRobotFoupInfo.UICarrierColor = pmModule.GetCarrierUIColor(carrierRobotFoupInfo.UICarrierType, carrierRobotFoupInfo.UICarrierStatusEnum); carrierRobotFoupInfo.UIExitFoup = true; carrierRobotFoupInfo.UIStockerExitFoup = false; var stockerFoupInfo = CarrierManager.Instance.GetCarrier(carrierRobotFoupInfo.InternalModuleName); if (stockerFoupInfo != null) { stockerFoupInfo.UICarrierType = carrierRobotFoupInfo.CarrierType.ToString(); stockerFoupInfo.UICarrierWaferCount = carrierRobotFoupInfo.UICarrierWaferCount; stockerFoupInfo.UICarrierStatusEnum = carrierRobotFoupInfo.UICarrierStatusEnum; } } Singleton.Instance.SetUIWaferCount(carrierRobotFoupInfo, ModuleName.CarrierRobot, out var wafers); } } public override void Reset() { _alarmSignaRobotAlarmTrig.RST = true; //_trigAlarmReset?.SetPulseTrigger(true, out _); if (IsError) { CheckToPostMessage((int)MSG.Reset); } } public override bool PrepareTransfer(ModuleName robot, Hand blade, int targetSlot, EnumTransferType transferType, out string reason) { reason = string.Empty; return true; } public override bool TransferHandoff(ModuleName robot, Hand blade, int targetSlot, EnumTransferType transferType, out string reason) { reason = string.Empty; return true; } public override bool PostTransfer(ModuleName robot, Hand blade, int targetSlot, EnumTransferType transferType, out string reason) { reason = string.Empty; return true; } public override bool CheckReadyForTransfer(ModuleName robot, Hand blade, int targetSlot, EnumTransferType transferType, out string reason) { reason = string.Empty; return IsReady; } public override bool CheckReadyForMap(ModuleName robot, Hand blade, out string reason) { reason = string.Empty; return IsReady; } public override void NoteTransferStart(ModuleName robot, Hand blade, int targetSlot, EnumTransferType transferType) { CheckToPostMessage(MSG.InTransfer); } public override void NoteTransferStop(ModuleName robot, Hand blade, int targetSlot, EnumTransferType transferType) { if (FsmState == (int)STATE.InTransfer) CheckToPostMessage(MSG.TransferComplete); } public override bool Pick(ModuleName target, Hand blade, int targetSlot, out string reason) { CheckToPostMessage((int)MSG.Pick, target.ToString(), targetSlot, blade); reason = string.Empty; return true; } public override bool Place(ModuleName target, Hand blade, int targetSlot, out string reason) { CheckToPostMessage((int)MSG.Place, target.ToString(), targetSlot, blade); reason = string.Empty; return true; } public bool Goto(ModuleName target, Hand blade, int targetSlot, bool isPickReady, out string reason) { CheckToPostMessage((int)MSG.Goto, target.ToString(), targetSlot, blade, isPickReady); reason = string.Empty; return true; } public override bool Load(ModuleName target, Hand blade, int targetSlot, ModuleName destinationStocker, CarrierType carrierType, string reservedCarrierId, out string reason) { CheckToPostMessage((int)MSG.Load, target.ToString(), targetSlot, blade, destinationStocker, carrierType, reservedCarrierId); reason = string.Empty; return true; } public override bool Unload(ModuleName target, Hand blade, int targetSlot, out string reason) { CheckToPostMessage((int)MSG.Unload, target.ToString(), targetSlot, blade); reason = string.Empty; return true; } public void CarrierIDReadSuccess(string carrierID) { } public void CarrierIDReadFail() { } public void MappingComplete(string carrierID, string slotmap) { } public void LoadportError(string errorcode) { } public void LoadComplete() { } public void UnloadComplete() { } public void OnLPHomed() { } public void OnE84HandoffStart(bool isload) { } public void OnE84HandoffComplete(bool isload) { } public void CarrierArrive() { } public void CarrerRemove(string carrierID) { } private bool FsmReset(object[] param) { if (IsError) { CarrierRobotDevice.RobotReset(); if (Singleton.Instance.IsAutoMode || Singleton.Instance.IsReturnWafer) { Singleton.Instance.ResetTask(ModuleHelper.Converter(Module)); } } return true; } private bool FsmOnError(object[] param) { if (FsmState == (int)STATE.Error) { return false; } AbortRoutine(); if (FsmState == (int)STATE.Init) return false; return true; } private bool FsmExitIdle(object[] param) { return true; } private bool FsmEnterIdle(object[] param) { return true; } private bool FsmExitError(object[] param) { return true; } private bool FsmEnterError(object[] param) { if (OnEnterError != null) OnEnterError(Module); return true; } private bool FsmAbortTask(object[] param) { if (!CarrierRobotDevice.IsReady()) CarrierRobotDevice.Abort(); AbortRoutine(); return true; } private bool FsmToInit(object[] param) { return true; } private bool FsmToIdle(object[] param) { return true; } private bool FsmMonitorLoadTask(object[] param) { Result ret = MonitorRoutine(); if (ret == Result.FAIL) { PostMsg(MSG.Error); return false; } if (ret == Result.DONE) IsOnline = true; return ret == Result.DONE; } private bool FsmMonitorUnloadTask(object[] param) { Result ret = MonitorRoutine(); if (ret == Result.FAIL) { PostMsg(MSG.Error); return false; } return ret == Result.DONE; } private bool FsmStartLoad(object[] param) { QueueRoutine.Clear(); _loadRoutine.Init(ModuleHelper.Converter(param[0].ToString()), (int)param[1], (Hand)param[2], ModuleHelper.Converter(param[3].ToString()), (CarrierType)param[4], param[5].ToString(), param.Length > 6 ? (bool)param[6] : false); QueueRoutine.Enqueue(_loadRoutine); Result ret = QueueRoutine.Peek().Start(); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool FsmStartUnload(object[] param) { _unloadRoutine.Init(ModuleHelper.Converter(param[0].ToString()), (int)param[1], (Hand)param[2], param.Length > 3 ? (bool)param[3] : false); Result ret = StartRoutine(_unloadRoutine); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool FsmStartHome(object[] param) { if (IsError) { if (Singleton.Instance.IsAutoMode || Singleton.Instance.IsReturnWafer) { Singleton.Instance.ResetTask(ModuleHelper.Converter(Module)); } } Result ret = StartRoutine(_home); if (ret == Result.FAIL || ret == Result.DONE) return false; _isInit = false; return ret == Result.RUN; } private bool FsmStartPick(object[] param) { _pick.Init(ModuleHelper.Converter(param[0].ToString()), (int)param[1], (Hand)param[2], param.Length > 3 ? (bool)param[3] : false); Result ret = StartRoutine(_pick); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool FsmStartPlace(object[] param) { _place.Init(ModuleHelper.Converter(param[0].ToString()), (int)param[1], (Hand)param[2], param.Length > 3 ? (bool)param[3] : false); Result ret = StartRoutine(_place); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool FsmStartGoto(object[] param) { _goto.Init(ModuleHelper.Converter(param[0].ToString()), (int)param[1], (Hand)param[2], (bool)param[3], param.Length > 34 ? (bool)param[4] : false); Result ret = StartRoutine(_goto); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool FsmStartSwap(object[] param) { _swap.Init(ModuleHelper.Converter(param[0].ToString()), ModuleHelper.Converter(param[1].ToString()), (int)param[2], (Hand)param[3]); Result ret = StartRoutine(_swap); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool FsmStartCycleSwap(object[] param) { _cycleSwap.Init(ModuleHelper.Converter(param[0].ToString()), ModuleHelper.Converter(param[1].ToString()), (int)param[2], (Hand)param[3], Convert.ToInt32(param[4] == null ? 0 : param[4])); Result ret = StartRoutine(_cycleSwap); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool FsmMonitorHomeTask(object[] param) { Result ret = MonitorRoutine(); if (ret == Result.FAIL) { PostMsg(MSG.Error); return false; } if (ret == Result.DONE) { _alarmSignaRobotAlarmTrig.RST = true; _isInit = true; return true; } return false; } private bool FsmMonitorTask(object[] param) { Result ret = MonitorRoutine(); if (ret == Result.FAIL) { PostMsg(MSG.Error); return false; } return ret == Result.DONE; } } }