using System; 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.Utilities; using Aitex.Sorter.Common; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Schedulers; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Efems.Rorzes; using MECF.Framework.RT.ModuleLibrary.AlignerModules; namespace JetEfemLib.Aligners { public class AlignerModule : AlignerModuleBase { private FutureAligner _alignerDevice; public enum STATE { NotInstall, Init, Idle, Homing, MapWaferPresence, Error, NotConnect, InTransfer, Aligning, Lifting, } public enum MSG { Home, Connected, Disconnected, MapWaferPresence, Align, Reset, Abort, Error, ToInit, InTransfer, TransferComplete, Lift } public event Action OnEnterError; public override bool IsReady { get { return FsmState == (int)STATE.Idle && CheckAllMessageProcessed() && !_alignerDevice.IsBusy; } } public override bool IsError { get { return FsmState == (int)STATE.Error; } } private bool _isInit; public override bool IsInit { get { return _isInit; } } private AlignerHomeRoutine _home; private AlignerAlignRoutine _align; private AlignerLiftRoutine _lift; public AlignerModule(ModuleName module) : base(1) { Name = module.ToString(); Module = module.ToString(); IsOnline = true; } public override bool Initialize() { InitRoutine(); InitDevice(); InitFsm(); InitOp(); InitData(); return base.Initialize(); } private void InitRoutine() { _home = new AlignerHomeRoutine(this); _align = new AlignerAlignRoutine(this); _lift = new AlignerLiftRoutine(this); } public void InitDevice() { _alignerDevice = DEVICE.GetDevice($"{ModuleName.Aligner1}.{ModuleName.Aligner1}"); } private void InitData() { DATA.Subscribe($"{Module}.Status", () => StringFsmStatus); DATA.Subscribe($"{Module}.IsOnline", () => IsOnline); DATA.Subscribe($"{Module}.WaferSize", () => WaferManager.Instance.GetWaferSize(ModuleHelper.Converter(Module), 0).ToString()); } private void InitOp() { OP.Subscribe($"{Module}.Home", (string cmd, object[] args) => CheckToPostMessage((int)MSG.Home)); OP.Subscribe($"{Module}.Reset", (string cmd, object[] args) => CheckToPostMessage((int)MSG.Reset)); OP.Subscribe($"{Module}.Align", (string cmd, object[] args) => CheckToPostMessage((int)MSG.Align,args)); OP.Subscribe($"{Module}.Lift", (string cmd, object[] args) => CheckToPostMessage((int)MSG.Lift, args)); } private void InitFsm() { EnumLoop.ForEach((item) => { MapState((int)item, item.ToString()); }); EnumLoop.ForEach((item) => { MapMessage((int)item, item.ToString()); }); EnableFsm(50, IsInstalled ? STATE.Init : STATE.NotInstall); //Error AnyStateTransition(MSG.Error, FsmOnError, STATE.Error); Transition(STATE.Error, MSG.Reset, FsmReset, STATE.Idle); EnterExitTransition(STATE.Error, FsmEnterError, FSM_MSG.NONE, FsmExitError); //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); AnyStateTransition(MSG.ToInit, FsmToInit, STATE.Init); //idle EnterExitTransition(STATE.Idle, FsmEnterIdle, FSM_MSG.NONE, FsmExitIdle); //align Transition(STATE.Idle, MSG.Align, FsmStartAlign, STATE.Aligning); Transition(STATE.Aligning, FSM_MSG.TIMER, FsmMonitorAlignTask, STATE.Idle); Transition(STATE.Aligning, MSG.Error, null, STATE.Init); Transition(STATE.Aligning, MSG.Abort, FsmAbortTask, STATE.Init); //lift Transition(STATE.Idle, MSG.Lift, FsmStartLift, STATE.Lifting); Transition(STATE.Lifting, FSM_MSG.TIMER, FsmMonitorLiftTask, STATE.Idle); Transition(STATE.Lifting, MSG.Error, null, STATE.Init); Transition(STATE.Lifting, MSG.Abort, FsmAbortTask, STATE.Init); } #region Service Functions public override bool Align(double angle) { return CheckToPostMessage((int)MSG.Align,angle); } public override bool Lift(bool isUp) { return CheckToPostMessage((int)MSG.Lift, isUp); } 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 Reset() { if (IsError) { if (_alignerDevice.IsError) { _alignerDevice.Reset(); } 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; if (transferType == EnumTransferType.Pick) { return IsReady&&WaferManager.Instance.CheckHasWafer(Module, targetSlot); } if (transferType == EnumTransferType.Place) { return IsReady&&WaferManager.Instance.CheckNoWafer(Module, targetSlot); } return false; } 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); } private bool FsmReset(object[] param) { if (!_isInit) { PostMsg(MSG.ToInit); return false; } if (_alignerDevice.IsError) { EV.PostWarningLog(Module, $"{Module} in error, home to recover"); PostMsg(MSG.ToInit); return false; } 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) { AbortRoutine(); return true; } private bool FsmStartHome(object[] param) { RState ret = StartRoutine(_home); if (ret == RState.Failed || ret == RState.End) return false; _isInit = false; return ret == RState.Running; } private bool FsmMonitorHomeTask(object[] param) { RState ret = MonitorRoutine(); if (ret == RState.Failed || ret == RState.Timeout) { PostMsg(MSG.Error); return false; } if (ret == RState.End) { _isInit = true; return true; } return false; } private bool FsmStartAlign(object[] param) { _align.Init(Convert.ToDouble(param[0])); RState ret = StartRoutine(_align); if (ret == RState.Failed || ret == RState.End) return false; _isInit = false; return ret == RState.Running; } private bool FsmStartLift(object[] param) { _lift.Init((bool)param[0]); RState ret = StartRoutine(_lift); if (ret == RState.Failed || ret == RState.End) return false; _isInit = false; return ret == RState.Running; } private bool FsmMonitorAlignTask(object[] param) { RState ret = MonitorRoutine(); if (ret == RState.Failed) { PostMsg(MSG.Error); return false; } if (ret == RState.End) { _isInit = true; return true; } return false; } private bool FsmMonitorLiftTask(object[] param) { RState ret = MonitorRoutine(); if (ret == RState.Failed) { PostMsg(MSG.Error); return false; } if (ret == RState.End) { _isInit = true; return true; } return false; } private bool FsmToInit(object[] param) { return true; } private bool FsmToIdle(object[] param) { return true; } #endregion } }