using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Device; using Aitex.Core.RT.Event; using Aitex.Core.RT.Fsm; using Aitex.Core.RT.OperationCenter; using Aitex.Core.RT.Routine; using Aitex.Core.Util; using Aitex.Core.Utilities; using Aitex.Sorter.Common; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Schedulers; using System; namespace Mainframe.EFEMs { public class EFEMModule : EFEMModuleBase { public enum STATE { NotInstall, Init, Idle, Homing, Cooling, Error, OpenSlitValve, CloseSlitValve, } public enum MSG { Home, Reset, Abort, Error, ToInit, SetOnline, SetOffline, OpenSlitValve, CloseSlitValve, }; public WaferRobotModule WaferRobotModule { get; set; } public TrayRobotModule TrayRobotModule { get; set; } public override bool IsReady { get { return FsmState == (int)STATE.Idle && CheckAllMessageProcessed(); } } public override bool IsError { get { return FsmState == (int)STATE.Error; } } public override bool IsInit { get { return FsmState == (int)STATE.Init; } } public bool IsBusy { get { return !IsInit && !IsError && !IsReady; } } public override bool IsIdle { get { return FsmState == (int)STATE.Idle && CheckAllMessageProcessed(); } } public bool IsAlarm { get { return FsmState == (int)STATE.Error; } } public event Action OnEnterError; private EfemSlitValveRoutine _slitValveRoutine; private bool _isInit; public SicEFEM _cassetteDevice { get; set; } public EFEMModule(ModuleName module) : base(1) { Module = module.ToString(); Name = module.ToString(); IsOnline = false; EnumLoop.ForEach((item) => { MapState((int)item, item.ToString()); }); EnumLoop.ForEach((item) => { MapMessage((int)item, item.ToString()); }); EnableFsm(50, IsInstalled ? STATE.Init : STATE.NotInstall); } public override bool Initialize() { InitRoutine(); InitDevice(); InitFsm(); InitOp(); InitData(); WaferRobotModule.Initialize(); TrayRobotModule.Initialize(); return base.Initialize(); } private void InitRoutine() { ModuleName module = ModuleHelper.Converter(Module); _slitValveRoutine = new EfemSlitValveRoutine(); } private void InitDevice() { _cassetteDevice = DEVICE.GetDevice($"{Module}.{Module}"); WaferRobotModule = new WaferRobotModule(ModuleName.WaferRobot); TrayRobotModule = new TrayRobotModule(ModuleName.TrayRobot); } private void InitFsm() { //Error AnyStateTransition(MSG.Error, FsmOnError, STATE.Error); AnyStateTransition(FSM_MSG.ALARM, FsmOnError, STATE.Error); Transition(STATE.Error, MSG.Reset, FsmReset, STATE.Idle); EnterExitTransition(STATE.Error, FsmEnterError, FSM_MSG.NONE, FsmExitError); //Home 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((int)STATE.Homing, FsmEnterIdle, (int)FSM_MSG.NONE, FsmExitIdle); AnyStateTransition(MSG.ToInit, FsmToInit, STATE.Init); //Online Transition(STATE.Idle, MSG.SetOnline, FsmStartSetOnline, STATE.Idle); Transition(STATE.Idle, MSG.SetOffline, FsmStartSetOffline, STATE.Idle); //open SlitValve Transition(STATE.Idle, MSG.OpenSlitValve, FsmStartOpenSlitValve, STATE.OpenSlitValve); Transition(STATE.OpenSlitValve, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.OpenSlitValve, MSG.Abort, FsmAbortTask, STATE.Idle); //close SlitValve Transition(STATE.Idle, MSG.CloseSlitValve, FsmStartCloseSlitValve, STATE.CloseSlitValve); Transition(STATE.CloseSlitValve, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.CloseSlitValve, MSG.Abort, FsmAbortTask, STATE.Idle); } private void InitOp() { OP.Subscribe($"{Name}.Home", (string cmd, object[] args) => CheckToPostMessage((int)MSG.Home)); OP.Subscribe($"{Name}.Reset", (string cmd, object[] args) => CheckToPostMessage((int)MSG.Reset)); OP.Subscribe($"{Name}.Abort", (string cmd, object[] args) => CheckToPostMessage((int)MSG.Abort)); OP.Subscribe($"{Module}.SetOnline", (string cmd, object[] args) => CheckToPostMessage((int)MSG.SetOnline)); OP.Subscribe($"{Module}.SetOffline", (string cmd, object[] args) => CheckToPostMessage((int)MSG.SetOffline)); OP.Subscribe($"{Module}.PickWafer", (string cmd, object[] args) => WaferRobotModule.PickWafer(args)); OP.Subscribe($"{Module}.PlaceWafer", (string cmd, object[] args) => WaferRobotModule.PlaceWafer(args)); OP.Subscribe($"{Module}.MapWafer", (string cmd, object[] args) => WaferRobotModule.MapWafer(args)); OP.Subscribe($"{Module}.RobotHome", (string cmd, object[] args) => WaferRobotModule.Home(out _) && TrayRobotModule.Home(out _)); OP.Subscribe($"{Module}.PickTray", (string cmd, object[] args) => TrayRobotModule.PickTray(args)); OP.Subscribe($"{Module}.PlaceTray", (string cmd, object[] args) => TrayRobotModule.PlaceTray(args)); OP.Subscribe($"{Module}.MapTray", (string cmd, object[] args) => TrayRobotModule.MapTray(args)); OP.Subscribe($"{Module}.OpenSlitValve", (string cmd, object[] args) => { return CheckToPostMessage((int)MSG.OpenSlitValve, args[0], args[1]); }); OP.Subscribe($"{Module}.CloseSlitValve", (string cmd, object[] args) => { return CheckToPostMessage((int)MSG.CloseSlitValve, args[0], args[1]); }); } private void InitData() { DATA.Subscribe($"{Name}.Status", () => StringFsmStatus); DATA.Subscribe($"{Name}.IsOnline", () => IsOnline); DATA.Subscribe($"{Name}.IsBusy", () => IsBusy); DATA.Subscribe($"{Module}.IsAlarm", () => IsAlarm); } private bool FsmOnError(object[] param) { IsOnline = false; if (FsmState == (int)STATE.Error) { return false; } if (FsmState == (int)STATE.Init) return false; return true; } private bool FsmReset(object[] param) { if (!_isInit) { PostMsg(MSG.ToInit); return false; } WaferRobotModule.Reset(); TrayRobotModule.Reset(); return true; } private bool FsmExitError(object[] param) { return true; } private bool FsmEnterError(object[] param) { if (OnEnterError != null) OnEnterError(Module); return true; } private bool FsmStartHome(object[] param) { return WaferRobotModule.Home(out _) && TrayRobotModule.Home(out _); } private bool FsmMonitorHomeTask(object[] param) { Result waferRobotRet = WaferRobotModule.MonitorRoutine(); Result trayRobotRet = TrayRobotModule.MonitorRoutine(); if (waferRobotRet == Result.FAIL || trayRobotRet == Result.FAIL) { PostMsg(MSG.Error); return false; } if (waferRobotRet == Result.DONE && trayRobotRet == Result.DONE) { _isInit = true; OP.DoOperation($"{Module}.ResetTask"); return true; } return false; } private bool FsmAbortTask(object[] param) { AbortRoutine(); WaferRobotModule.Abort(); TrayRobotModule.Abort(); return true; } private bool FsmExitIdle(object[] param) { return true; } private bool FsmEnterIdle(object[] param) { return true; } private bool FsmToInit(object[] param) { WaferRobotModule.Reset(); TrayRobotModule.Reset(); return true; } private bool FsmStartSetOffline(object[] param) { IsOnline = false; WaferRobotModule.IsOnline = false; TrayRobotModule.IsOnline = false; return true; } private bool FsmStartSetOnline(object[] param) { IsOnline = true; WaferRobotModule.IsOnline = true; TrayRobotModule.IsOnline = true; return true; } private bool FsmMonitorTask(object[] param) { Result ret = MonitorRoutine(); if (ret == Result.FAIL) { PostMsg(MSG.Error); return false; } return ret == Result.DONE; } public override bool Home(out string reason) { CheckToPostMessage((int)MSG.Home); reason = string.Empty; return true; } public override bool CheckAcked(int entityTaskToken) { return FsmState == (int)STATE.Idle && CheckAllMessageProcessed(); //return true; } 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 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 true; } public override bool CheckReadyForMap(ModuleName robot, Hand blade, out string reason) { reason = string.Empty; return true; } public void InvokeOffline() { PostMsg((int)MSG.SetOffline); } public void InvokeOnline() { PostMsg((int)MSG.SetOnline); } public override bool MapWafer(ModuleName target) { if (WaferRobotModule.MapWafer(target)) { return true; } return false; } public override bool PickWafer(ModuleName target, Hand blade, int targetSlot) { if (WaferRobotModule.PickWafer(target, blade, targetSlot)) { return true; } return false; } public override bool PlaceWafer(ModuleName target, Hand blade, int targetSlot) { if (WaferRobotModule.PlaceWafer(target, blade, targetSlot)) { return true; } return false; } public override bool GotoWafer(ModuleName target, Hand blade, int targetSlot) { throw new NotImplementedException(); } public override bool MapTray(ModuleName target) { if (TrayRobotModule.MapTray(target)) { return true; } return false; } public override bool PickTray(ModuleName target, Hand blade, int targetSlot) { if (TrayRobotModule.PickTray(target, blade, targetSlot)) { return true; } return false; } public override bool PlaceTray(ModuleName target, Hand blade, int targetSlot) { if (TrayRobotModule.PlaceTray(target, blade, targetSlot)) { return true; } return false; } public override bool GotoTray(ModuleName target, Hand blade, int targetSlot) { throw new NotImplementedException(); } private bool FsmStartOpenSlitValve(object[] param) { if (ModuleHelper.Converter(param[1].ToString()) == ModuleName.WaferRobot && !WaferRobotModule.IsIdle) return false; if (ModuleHelper.Converter(param[1].ToString()) == ModuleName.TrayRobot && !TrayRobotModule.IsIdle) return false; _slitValveRoutine.Init(ModuleHelper.Converter(param[0].ToString()), ModuleHelper.Converter(param[1].ToString()), true); Result ret = StartRoutine(_slitValveRoutine); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool FsmStartCloseSlitValve(object[] param) { if (ModuleHelper.Converter(param[1].ToString()) == ModuleName.WaferRobot && !WaferRobotModule.IsIdle) return false; if (ModuleHelper.Converter(param[1].ToString()) == ModuleName.TrayRobot && !TrayRobotModule.IsIdle) return false; _slitValveRoutine.Init(ModuleHelper.Converter(param[0].ToString()), ModuleHelper.Converter(param[1].ToString()), false); Result ret = StartRoutine(_slitValveRoutine); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } public int InvokeError() { if (CheckToPostMessage((int)MSG.Error)) return (int)MSG.Error; return (int)FSM_MSG.NONE; } } }