using System; using System.Diagnostics; using System.Linq; 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.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.RT.EquipmentLibrary.HardwareUnits.LoadPorts; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robot; namespace FurnaceRT.Equipments.WaferRobots { public partial class WaferRobotModule : WaferRobotModuleBase, IE87CallBack { public enum STATE { Init, Idle, Error, Homing, InTransfer, Picking, Placing, Mapping, Swaping, } public enum MSG { Home, Reset, Init, Error, Abort, InTransfer, TransferComplete, Pick, Place, Map, PickRetry, PlaceRetry, MapRetry, Swap, } 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 WaferRobotHome _home; private WaferRobotPick _pick; private WaferRobotPlace _place; private WaferRobotMap _map; private WaferRobotSwap _swap; public WaferRobotModule(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() { _home = new WaferRobotHome(this); _pick = new WaferRobotPick(this); _place = new WaferRobotPlace(this); _map = new WaferRobotMap(this); _swap = new WaferRobotSwap(this); } private void InitData() { DATA.Subscribe($"{Module}.Status", () => StringFsmStatus); DATA.Subscribe($"{Module}.SwapCycledCount", () => _swap.LoopCounter); DATA.Subscribe($"{Module}.IsOnline", () => IsOnline); } 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}.Swap", (string cmd, object[] args) => CheckToPostMessage((int)MSG.Swap, args)); OP.Subscribe($"{Module}.Mapping", (string cmd, object[] args) => CheckToPostMessage((int)MSG.Map, args)); 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); //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); //map Transition(STATE.Error, MSG.MapRetry, FsmStartMap, STATE.Mapping); Transition(STATE.Idle, MSG.Map, FsmStartMap, STATE.Mapping); Transition(STATE.Mapping, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.Mapping, MSG.Abort, FsmAbortTask, STATE.Idle); //swap Transition(STATE.Idle, MSG.Swap, FsmStartSwap, STATE.Swaping); Transition(STATE.Swaping, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.Swaping, 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(); WaferRobotDevice.NoteError(""); } } 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 override bool Map(ModuleName target, Hand blade, int slotNumber, string slotMap, bool isCompareWithSlotMap, bool isCreateWafer, out string reason) { CheckToPostMessage((int)MSG.Map, target.ToString(), slotNumber, blade, slotMap, isCompareWithSlotMap, isCreateWafer); 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) { WaferRobotDevice.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 (!WaferRobotDevice.IsReady()) WaferRobotDevice.Abort(); AbortRoutine(); return true; } private bool FsmToInit(object[] param) { return true; } private bool FsmToIdle(object[] param) { return true; } private bool FsmMonitorTask(object[] param) { Result ret = MonitorRoutine(); if (ret == Result.FAIL) { PostMsg(MSG.Error); return false; } 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 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 FsmStartMap(object[] param) { _map.Init(ModuleHelper.Converter(param[0].ToString()), (int)param[1], (Hand)param[2], param[3].ToString(), (bool)param[4], (bool)param[5], param.Length > 6 ? (bool)param[6] : false); Result ret = StartRoutine(_map); 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], (int)param[3],(Hand)param[4]); Result ret = StartRoutine(_swap); 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 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 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; } } }