EfemEntity.cs 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027
  1. using System;
  2. using System.Diagnostics;
  3. using System.Collections.Generic;
  4. using Aitex.Core.Common;
  5. using Aitex.Core.RT.DataCenter;
  6. using Aitex.Core.RT.Event;
  7. using Aitex.Core.RT.Fsm;
  8. using Aitex.Core.RT.OperationCenter;
  9. using Aitex.Core.RT.SCCore;
  10. using Aitex.Core.Utilities;
  11. using Aitex.Core.Util;
  12. using Aitex.Core.RT.Log;
  13. using Aitex.Sorter.Common;
  14. using MECF.Framework.Common.Equipment;
  15. using MECF.Framework.Common.Schedulers;
  16. using MECF.Framework.Common.SubstrateTrackings;
  17. using Venus_Core;
  18. using Venus_RT;
  19. using Venus_RT.Devices;
  20. using Venus_RT.Devices.YASKAWA;
  21. using Venus_RT.Devices.EFEM;
  22. using Venus_RT.Modules.LPs;
  23. using Venus_RT.Modules.EFEM;
  24. namespace Venus_RT.Modules
  25. {
  26. class EfemEntity : Entity, IEntity, IModuleEntity
  27. {
  28. //private int _bigWafer = 0;
  29. //private int _midWafer = 0;
  30. //private int _smallWafer = 0;
  31. public enum STATE
  32. {
  33. Unknown, // 0
  34. Initializing, // 1
  35. Idle, // 2
  36. Error, // 3
  37. Picking, // 4
  38. Placing, // 5
  39. Aligning, // 6
  40. Mapping, // 7
  41. Init, // 8
  42. Orgshing, // 9
  43. Lifting, // 10
  44. InitingAL, // 11
  45. InitingRB, // 12
  46. Extending, // 13
  47. Retracting, // 14
  48. //SettingLamp, // 15
  49. Swapping,
  50. Gotoing,
  51. Gripping,
  52. Ungripping,
  53. Fliping,
  54. }
  55. public enum MSG
  56. {
  57. HomeAll, // 0
  58. Pick, // 1
  59. Place, // 2
  60. Align, // 3
  61. ActionDone, // 4
  62. MoveCmd, // 6
  63. Recover, // 8
  64. Goto, // 9
  65. Error, // 10
  66. Online, // 11
  67. CommReady, // 12
  68. Lift, // 13
  69. HomeAL, // 14
  70. HomeRB, // 15
  71. Extend, // 16
  72. Retract, // 17
  73. PMLiftPinUp, // 18
  74. PMLiftPinDown, // 19
  75. TurnOffBuzzer,
  76. Abort,
  77. Map,
  78. ToInit,
  79. Cool,
  80. Swap,
  81. Grip,
  82. Ungrip,
  83. Flip,
  84. LiftActionDone,
  85. Offline,
  86. Light,
  87. }
  88. public enum EfemType
  89. {
  90. FutureEfem = 1,
  91. JetEfem = 2,
  92. BrooksEFEM = 3,
  93. }
  94. public bool IsIdle
  95. {
  96. get { return fsm.State == (int)STATE.Idle; }
  97. }
  98. public bool IsError
  99. {
  100. get { return fsm.State == (int)STATE.Error; }
  101. }
  102. public bool IsInit
  103. {
  104. get { return fsm.State == (int)STATE.Unknown || fsm.State == (int)STATE.Init; }
  105. }
  106. public bool IsBusy
  107. {
  108. get { return !IsInit && !IsError && !IsIdle; }
  109. }
  110. public bool IsOnline { get; internal set; }
  111. public RState RobotStatus
  112. {
  113. get
  114. {
  115. if (_efem.Status != RState.Running)
  116. {
  117. if (_robotWatch.ElapsedMilliseconds < 200)
  118. return RState.Running;
  119. else
  120. return _efem.Status;
  121. }
  122. else
  123. return RState.Running;
  124. }
  125. }
  126. public bool Check(int msg, out string reason, params object[] args)
  127. {
  128. throw new NotImplementedException();
  129. }
  130. // Fields
  131. //
  132. private readonly string Name;
  133. private readonly EfemBase _efem;
  134. private readonly LoadPortModule[] _lpms = new LoadPortModule[3];
  135. private readonly EfemSignalTower _signalTower;
  136. private readonly EfemType _efemType;
  137. public EfemBase EfemDevice => _efem;
  138. public EfemType EFEMType => _efemType;
  139. // routine
  140. private readonly EfemPickRoutine _pickRoutine;
  141. private readonly EfemPlaceRoutine _placeRoutine;
  142. private readonly EfemSwapRoutine _swapRoutine;
  143. private readonly EfemHomeRoutine _homeRoutine;
  144. private readonly EFEMAlignRoutine _alignRoutine;
  145. private string LiftMessage;
  146. private Stopwatch _robotWatch = new Stopwatch();
  147. private R_TRIG _robotIdleTrigger = new R_TRIG();
  148. public LoadPortModule GetLoadportModule(int lpNumber)
  149. {
  150. if(lpNumber<=0)
  151. {
  152. return null;
  153. }
  154. if(_lpms.Length>=lpNumber)
  155. {
  156. return _lpms[lpNumber-1];
  157. }
  158. return null;
  159. }
  160. // Constructor
  161. //
  162. public EfemEntity()
  163. {
  164. _efemType = (EfemType)SC.GetValue<int>($"EFEM.EfemType");
  165. _efem = new JetEfem();
  166. _signalTower = new EfemSignalTower(_efem);
  167. Name = ModuleName.EFEM.ToString();
  168. _homeRoutine = new EfemHomeRoutine(_efem);
  169. _pickRoutine = new EfemPickRoutine(_efem);
  170. _placeRoutine = new EfemPlaceRoutine(_efem);
  171. _swapRoutine = new EfemSwapRoutine(_efem);
  172. _alignRoutine = new EFEMAlignRoutine(_efem);
  173. InitFsmMap();
  174. }
  175. public void NotifyLP(ModuleName mod, LoadportEntity.MSG msg)
  176. {
  177. _lpms[mod - ModuleName.LP1].PostMsg(msg);
  178. }
  179. public void NotifyLPError(ModuleName mod )
  180. {
  181. _lpms[mod - ModuleName.LP1].PostMsg(LoadportEntity.MSG.ActionDone);
  182. //_lpms[mod - ModuleName.LP1]..OnError();
  183. }
  184. protected override bool Init()
  185. {
  186. _lpms[0] = new LoadPortModule(ModuleName.LP1, _efem);
  187. _lpms[1] = new LoadPortModule(ModuleName.LP2, _efem);
  188. _lpms[2] = new LoadPortModule(ModuleName.LP3, _efem);
  189. _lpms[0].Initialize();
  190. _lpms[1].Initialize();
  191. _lpms[2].Initialize();
  192. OP.Subscribe($"{ModuleName.EFEM}.{EfemOperation.Home}", (cmd, args) => { PostMsg(MSG.HomeAll); return true; });
  193. OP.Subscribe($"{ModuleName.EFEM}.{EfemOperation.ClearError}", (cmd, args) => { PostMsg(MSG.Recover); return true; });
  194. OP.Subscribe($"{ModuleName.EFEM}.{EfemOperation.TurnOffBuzzer}", (cmd, args) => { PostMsg(MSG.TurnOffBuzzer); return true; });
  195. //OP.Subscribe($"{ModuleName.EFEM}.{EfemOperation.SwitchOnBuzzerAndRed}", (cmd, args) => { PostMsg(MSG.SwitchOnBuzzerAndRed); return true; });
  196. OP.Subscribe($"{ModuleName.EFEM}.Online", (cmd, args) =>
  197. {
  198. PostMsg(MSG.Online, args[0]); return true;
  199. });
  200. OP.Subscribe($"{ModuleName.EfemRobot}.{EfemOperation.Pick}", (cmd, args) => { PostMsg(MSG.Pick, args[0]); return true; });
  201. OP.Subscribe($"{ModuleName.EfemRobot}.{EfemOperation.Place}", (cmd, args) => { PostMsg(MSG.Place, args[0]); return true; });
  202. OP.Subscribe($"{ModuleName.EfemRobot}.{EfemOperation.Swap}", (cmd, args) => { PostMsg(MSG.Swap, args[0]); return true; });
  203. OP.Subscribe($"{ModuleName.EfemRobot}.{EfemOperation.Abort}", (cmd, args) => { PostMsg(MSG.Abort); return true; });
  204. OP.Subscribe($"{ModuleName.EfemRobot}.{EfemOperation.Home}", (cmd, args) => { PostMsg(MSG.HomeRB); return true; });
  205. OP.Subscribe($"{ModuleName.EfemRobot}.{EfemOperation.Grip}", (cmd, args) =>
  206. {
  207. bool isGrip = ((string)args[0]).ToLower() == "on";
  208. PostMsg(isGrip ? MSG.Grip : MSG.Ungrip, args[1]);
  209. return true;
  210. });
  211. //OP.Subscribe($"{ModuleName.EfemRobot}.{EfemOperation.Flip}", (cmd, args) => { PostMsg(MSG.Flip, args[0]); return true; });
  212. OP.Subscribe($"{ModuleName.Aligner1}.{EfemOperation.Home}", (cmd, args) => { PostMsg(MSG.HomeAL, ModuleName.Aligner1); return true; });
  213. OP.Subscribe($"{ModuleName.Aligner2}.{EfemOperation.Home}", (cmd, args) => { PostMsg(MSG.HomeAL, ModuleName.Aligner2); return true; });
  214. OP.Subscribe($"{ModuleName.Cooling1}.{EfemOperation.Home}", (cmd, args) => { PostMsg(MSG.HomeAL, ModuleName.Cooling1); return true; });
  215. OP.Subscribe($"{ModuleName.Cooling2}.{EfemOperation.Home}", (cmd, args) => { PostMsg(MSG.HomeAL, ModuleName.Cooling2); return true; });
  216. OP.Subscribe($"{ModuleName.Aligner1}.{EfemOperation.Align}", (cmd, args) => { PostMsg(MSG.Align, ModuleName.Aligner1, args[0], args[1]); return true; });
  217. OP.Subscribe($"{ModuleName.Aligner2}.{EfemOperation.Align}", (cmd, args) => { PostMsg(MSG.Align, ModuleName.Aligner2); return true; });
  218. OP.Subscribe($"{ModuleName.Cooling1}.{EfemOperation.Align}", (cmd, args) => { PostMsg(MSG.Align, ModuleName.Cooling1); return true; });
  219. OP.Subscribe($"{ModuleName.Cooling2}.{EfemOperation.Align}", (cmd, args) => { PostMsg(MSG.Align, ModuleName.Cooling2); return true; });
  220. OP.Subscribe($"{ModuleName.Aligner1}.{EfemOperation.Lift}", (cmd, args) => { PostMsg(MSG.Lift, ModuleName.Aligner1); return true; });
  221. OP.Subscribe($"{ModuleName.Aligner2}.{EfemOperation.Lift}", (cmd, args) => { PostMsg(MSG.Lift, ModuleName.Aligner2); return true; });
  222. OP.Subscribe($"{ModuleName.Cooling1}.{EfemOperation.Lift}", (cmd, args) => { PostMsg(MSG.Lift, ModuleName.Cooling1); return true; });
  223. OP.Subscribe($"{ModuleName.Cooling2}.{EfemOperation.Lift}", (cmd, args) => { PostMsg(MSG.Lift, ModuleName.Cooling2); return true; });
  224. DATA.Subscribe($"{Name}.FsmState", () => ((STATE)fsm.State).ToString(),Aitex.Core.Util.SubscriptionAttribute.FLAG.IgnoreSaveDB);
  225. DATA.Subscribe($"{Name}.FsmPrevState", () => ((STATE)fsm.PrevState).ToString(), Aitex.Core.Util.SubscriptionAttribute.FLAG.IgnoreSaveDB);
  226. DATA.Subscribe($"{Name}.FsmLastMessage", GetFsmLastMessage, Aitex.Core.Util.SubscriptionAttribute.FLAG.IgnoreSaveDB);
  227. DATA.Subscribe($"{Name}.RobotMoveAction", () => (_efem.TMRobotMoveInfo), Aitex.Core.Util.SubscriptionAttribute.FLAG.IgnoreSaveDB);
  228. DATA.Subscribe($"{Name}.IsOnline", () => (IsOnline), Aitex.Core.Util.SubscriptionAttribute.FLAG.IgnoreSaveDB);
  229. _robotWatch.Restart();
  230. return true;
  231. }
  232. private void InitFsmMap()
  233. {
  234. fsm = new StateMachine<EfemEntity>("EFEM", (int)STATE.Unknown, 50);
  235. fsm.EnableRepeatedMsg(true);
  236. AnyStateTransition(FSM_MSG.TIMER, fnMonitor, FSM_STATE.SAME);
  237. AnyStateTransition(MSG.TurnOffBuzzer, fnTurnOffBuzzer, FSM_STATE.SAME);
  238. AnyStateTransition(MSG.Recover, fnRecover, STATE.Idle);
  239. AnyStateTransition(MSG.Error, fnError, STATE.Error);
  240. AnyStateTransition(MSG.Online, fnOnline, FSM_STATE.SAME);
  241. AnyStateTransition(MSG.Abort, fnAbortRobot, STATE.Idle);
  242. AnyStateTransition(MSG.ToInit, fnToInit, STATE.Init);
  243. AnyStateTransition(MSG.Light, fnSetLight, FSM_STATE.SAME);
  244. AnyStateTransition(MSG.CommReady, fnCommReady, STATE.Init);
  245. Transition(STATE.Init, FSM_MSG.TIMER, fnMonitor, STATE.Init);
  246. Transition(STATE.Idle, FSM_MSG.TIMER, fnMonitor, STATE.Idle);
  247. Transition(STATE.Error, FSM_MSG.TIMER, fnMonitor, STATE.Error);
  248. // Home
  249. Transition(STATE.Init, MSG.HomeAll, fnHomeAll, STATE.Initializing);
  250. Transition(STATE.Idle, MSG.HomeAll, fnHomeAll, STATE.Initializing);
  251. Transition(STATE.Error, MSG.HomeAll, fnHomeAll, STATE.Initializing);
  252. Transition(STATE.Initializing, FSM_MSG.TIMER, fnHomingTimeout, STATE.Idle);
  253. // Home Robot
  254. Transition(STATE.Idle, MSG.HomeRB, fnHomeRobot, STATE.InitingRB);
  255. Transition(STATE.InitingRB, FSM_MSG.TIMER, fnHomingTimeout, STATE.Idle);
  256. // Home Aligner
  257. Transition(STATE.Idle, MSG.HomeAL, fnHomeAligner, STATE.InitingAL);
  258. Transition(STATE.InitingAL, FSM_MSG.TIMER, fnHomingTimeout, STATE.Idle);
  259. // Pick wafer
  260. Transition(STATE.Idle, MSG.Pick, FnStartPick, STATE.Picking);
  261. Transition(STATE.Picking, FSM_MSG.TIMER, FnPickTimeout, STATE.Idle);
  262. Transition(STATE.Picking, MSG.Abort, FnAbortPick, STATE.Idle);
  263. // Place wafer
  264. Transition(STATE.Idle, MSG.Place, FnStartPlace, STATE.Placing);
  265. Transition(STATE.Placing, FSM_MSG.TIMER, FnPlaceTimeout, STATE.Idle);
  266. Transition(STATE.Placing, MSG.Abort, FnAbortPlace, STATE.Idle);
  267. // Swap wafer with LL sequence
  268. Transition(STATE.Idle, MSG.Swap, FnStartSwap, STATE.Swapping);
  269. Transition(STATE.Swapping, FSM_MSG.TIMER, FnSwapTimeout, STATE.Idle);
  270. Transition(STATE.Swapping, MSG.Abort, FnAbortSwap, STATE.Idle);
  271. // Goto
  272. Transition(STATE.Idle, MSG.Goto, fnGoto, STATE.Gotoing);
  273. Transition(STATE.Gotoing, MSG.ActionDone, fnActionDone, STATE.Idle);
  274. // Map
  275. Transition(STATE.Idle, MSG.Map, fnMap, STATE.Mapping);
  276. Transition(STATE.Mapping, MSG.ActionDone, fnActionDone, STATE.Idle);
  277. // Grip
  278. Transition(STATE.Idle, MSG.Grip, fnGrip, STATE.Gripping);
  279. Transition(STATE.Gripping, MSG.ActionDone, fnActionDone, STATE.Idle);
  280. // Ungrip
  281. Transition(STATE.Idle, MSG.Ungrip, fnUngrip, STATE.Ungripping);
  282. Transition(STATE.Ungripping, MSG.ActionDone, fnActionDone, STATE.Idle);
  283. // Aligner
  284. Transition(STATE.Idle, MSG.Lift, fnLift, STATE.Lifting);
  285. //Transition(STATE.Lifting, MSG.LiftActionDone, fnActionDone, STATE.Idle);
  286. Transition(STATE.Lifting, FSM_MSG.TIMER, fnLiftTimeout, STATE.Idle);
  287. Transition(STATE.Idle, MSG.Align, fnAlign, STATE.Aligning);
  288. Transition(STATE.Aligning, FSM_MSG.TIMER, fnAlignTimeout, STATE.Idle);
  289. Transition(STATE.Aligning, MSG.ActionDone, fnActionDone, STATE.Idle);
  290. EnumLoop<STATE>.ForEach((item) => { fsm.MapState((int)item, item.ToString()); });
  291. EnumLoop<MSG>.ForEach((item) => { fsm.MapMessage((int)item, item.ToString()); });
  292. Running = true;
  293. }
  294. private bool fnCommReady(object[] param)
  295. {
  296. return true;
  297. }
  298. private bool fnHomeAll(object[] param)
  299. {
  300. return _homeRoutine.Start(ModuleName.EFEM) == RState.Running;
  301. }
  302. private bool fnHomingTimeout(object[] param)
  303. {
  304. RState ret = _homeRoutine.Monitor();
  305. if (ret == RState.Failed || ret == RState.Timeout)
  306. {
  307. PostMsg(MSG.Error);
  308. return false;
  309. }
  310. return ret == RState.End;
  311. }
  312. private bool fnHomeRobot(object[] param)
  313. {
  314. return _homeRoutine.Start(ModuleName.EfemRobot) == RState.Running;
  315. }
  316. private bool fnHomeAligner(object[] param)
  317. {
  318. // module
  319. ModuleName unit = ModuleName.EFEM;
  320. if (param[0] is string s1)
  321. unit = ModuleNameString.ToEnum(s1);
  322. else if (param[0] is ModuleName mod)
  323. unit = mod;
  324. else
  325. throw new ArgumentException("Argument error");
  326. return _homeRoutine.Start(unit) == RState.Running;
  327. }
  328. private bool fnActionDone(object[] param)
  329. {
  330. return false;
  331. }
  332. public bool CheckToPostMessage(int msg, params object[] args)
  333. {
  334. if (!fsm.FindTransition(fsm.State, msg))
  335. {
  336. LOG.Write(eEvent.WARN_EFEM_COMMON_WARN, ModuleName.EFEM, $"{Name} is in {(STATE)fsm.State} state,can not do {(MSG)msg}");
  337. return false;
  338. }
  339. Running = true;
  340. fsm.PostMsg(msg, args);
  341. return true;
  342. }
  343. private bool fnMonitor(object[] param)
  344. {
  345. // robot idle check
  346. _robotIdleTrigger.CLK = _efem.Status != RState.Running;
  347. if (_robotIdleTrigger.Q)
  348. {
  349. _robotWatch.Restart();
  350. }
  351. _efem.Monitor();
  352. _signalTower.Monitor();
  353. return true;
  354. }
  355. private bool fnOnline(object[] param)
  356. {
  357. bool bOnlineFlag = (bool)param[0];
  358. if (_efem is EfemBase efem)
  359. {
  360. efem.SetOnline(bOnlineFlag);
  361. }
  362. IsOnline = bOnlineFlag;
  363. return true;
  364. }
  365. private string GetFsmLastMessage()
  366. {
  367. int msg = fsm.LastMsg;
  368. if (msg >= (int)MSG.HomeAll && msg <= (int)MSG.Error)
  369. return ((MSG)msg).ToString();
  370. if (msg == (int)FSM_MSG.TIMER)
  371. return "Timer";
  372. return msg.ToString();
  373. }
  374. private bool fnError(object[] param)
  375. {
  376. return true;
  377. }
  378. private bool fnToInit(object[] param)
  379. {
  380. return true;
  381. }
  382. private bool fnRecover(object[] param)
  383. {
  384. _efem.ClearError();
  385. //_efem.ExecuteAction();
  386. return true;
  387. }
  388. private bool fnAbortRobot(object[] param)
  389. {
  390. //_efem.ExecuteAction();
  391. return true;
  392. }
  393. private bool fnSetLight(object[] param)
  394. {
  395. LightType light = (LightType)param[0];
  396. LightStatus st = (LightStatus)param[1];
  397. _signalTower.SetLight(light, st);
  398. return true;
  399. }
  400. private bool fnTurnOffBuzzer(object[] param)
  401. {
  402. return false;
  403. }
  404. private bool FnStartPick(object[] param)
  405. {
  406. return _pickRoutine.Start(param) == RState.Running;
  407. }
  408. private bool FnPickTimeout(object[] param)
  409. {
  410. RState ret = _pickRoutine.Monitor();
  411. if (ret == RState.Failed || ret == RState.Timeout)
  412. {
  413. PostMsg(MSG.Error);
  414. Singleton<RouteManager>.Instance.InvokeAbort(new object[] { ModuleName.EFEM });
  415. return false;
  416. }
  417. return ret == RState.End;
  418. }
  419. private bool FnAbortPick(object[] param)
  420. {
  421. _pickRoutine.Abort();
  422. return true;
  423. }
  424. private bool FnStartPlace(object[] param)
  425. {
  426. return _placeRoutine.Start(param) == RState.Running;
  427. }
  428. private bool FnPlaceTimeout(object[] param)
  429. {
  430. RState ret = _placeRoutine.Monitor();
  431. if (ret == RState.Failed || ret == RState.Timeout)
  432. {
  433. PostMsg(MSG.Error);
  434. Singleton<RouteManager>.Instance.InvokeAbort(new object[] { ModuleName.EFEM });
  435. return false;
  436. }
  437. return ret == RState.End;
  438. }
  439. private bool FnAbortPlace(object[] param)
  440. {
  441. _placeRoutine.Abort();
  442. return true;
  443. }
  444. private bool FnStartSwap(object[] param)
  445. {
  446. return _swapRoutine.Start(param) == RState.Running;
  447. }
  448. private bool FnSwapTimeout(object[] param)
  449. {
  450. RState ret = _swapRoutine.Monitor();
  451. if (ret == RState.Failed || ret == RState.Timeout)
  452. {
  453. PostMsg(MSG.Error);
  454. Singleton<RouteManager>.Instance.InvokeAbort(new object[] { ModuleName.EFEM });
  455. return false;
  456. }
  457. return ret == RState.End;
  458. }
  459. private bool FnAbortSwap(object[] param)
  460. {
  461. _swapRoutine.Abort();
  462. return true;
  463. }
  464. private bool fnGoto(object[] param)
  465. {
  466. // module
  467. ModuleName unit = ModuleName.EFEM;
  468. if (param[0] is string s1)
  469. unit = ModuleNameString.ToEnum(s1);
  470. else if (param[0] is ModuleName mod)
  471. unit = mod;
  472. else
  473. throw new ArgumentException("Argument error");
  474. _efem.Goto(unit, Hand.Blade1);
  475. return true;
  476. }
  477. private bool fnLift(object[] param)
  478. {
  479. // module
  480. ModuleName unit = ModuleName.EFEM;
  481. if (param[0] is string s1)
  482. unit = ModuleNameString.ToEnum(s1);
  483. else if (param[0] is ModuleName mod)
  484. unit = mod;
  485. else
  486. throw new ArgumentException("Argument error");
  487. bool isUp = true;
  488. if (param.Length > 1)
  489. {
  490. isUp = (bool) param[1];
  491. }
  492. if (isUp)
  493. {
  494. if (!_efem.SetPinUp(unit))
  495. return false;
  496. }
  497. else
  498. {
  499. if (!_efem.SetPinDown(unit))
  500. return false;
  501. }
  502. LiftMessage = isUp ? "Up" : "Down";
  503. return true;
  504. }
  505. private bool fnLiftTimeout(object[] param)
  506. {
  507. if (LiftMessage == "Up")
  508. {
  509. return _efem.LiftIsDown == false && _efem.LiftIsUp == true;
  510. }
  511. else if (LiftMessage == "Down")
  512. {
  513. return _efem.LiftIsDown == true && _efem.LiftIsUp == false;
  514. }
  515. return false;
  516. }
  517. private bool fnAlign(object[] param)
  518. {
  519. return _alignRoutine.Start(param) == RState.Running;
  520. }
  521. private bool fnAlignTimeout(object[] param)
  522. {
  523. RState ret = _alignRoutine.Monitor();
  524. if (ret == RState.Failed || ret == RState.Timeout)
  525. {
  526. PostMsg(MSG.Error);
  527. return false;
  528. }
  529. return ret == RState.End;
  530. }
  531. private bool fnMap(object[] param)
  532. {
  533. // module
  534. ModuleName unit = ModuleName.EFEM;
  535. if (param[0] is string s1)
  536. unit = ModuleNameString.ToEnum(s1);
  537. else if (param[0] is ModuleName mod)
  538. unit = mod;
  539. else
  540. throw new ArgumentException("Argument error");
  541. if (!_efem.Map(unit))
  542. return false;
  543. return true;
  544. }
  545. private bool fnGrip(object[] param)
  546. {
  547. Hand arm = (Hand)Enum.Parse(typeof(Hand), (string)param[0]);
  548. if (!_efem.Grip(arm, true))
  549. return false;
  550. return true;
  551. }
  552. private bool fnUngrip(object[] param)
  553. {
  554. Hand arm = (Hand)Enum.Parse(typeof(Hand), (string)param[0]);
  555. if (!_efem.Grip(arm, false))
  556. return false;
  557. return true;
  558. }
  559. public int Invoke(string function, params object[] args)
  560. {
  561. switch (function)
  562. {
  563. case "Home":
  564. CheckToPostMessage((int)MSG.HomeAll);
  565. return (int)MSG.HomeAll;
  566. }
  567. return (int)FSM_MSG.NONE;
  568. }
  569. public bool CheckAcked(int msg)
  570. {
  571. return fsm.CheckExecuted(msg);
  572. }
  573. internal void InvokeReset()
  574. {
  575. if (fsm.State == (int) STATE.Error)
  576. {
  577. PostMsg((int)MSG.Recover);
  578. }
  579. }
  580. public int InvokeAlign(string module, int reserv, float angle)
  581. {
  582. if (CheckToPostMessage((int)MSG.Align, module, reserv, angle))
  583. return (int)MSG.Align;
  584. return (int)FSM_MSG.NONE;
  585. }
  586. public int InvokeLiftDown(string module)
  587. {
  588. if (CheckToPostMessage((int)MSG.Lift, module, false))
  589. return (int)MSG.Lift;
  590. return (int)FSM_MSG.NONE;
  591. }
  592. public int InvokePick(ModuleName source, int slot, Hand hand, WaferSize size)
  593. {
  594. if (CheckToPostMessage((int)MSG.Pick, source, slot, hand, size))
  595. return (int)MSG.Pick;
  596. return (int)FSM_MSG.NONE;
  597. }
  598. public int InvokeGoto(ModuleName source, int slot)
  599. {
  600. if (CheckToPostMessage((int)MSG.Goto, source, slot))
  601. return (int)MSG.Goto;
  602. return (int)FSM_MSG.NONE;
  603. }
  604. public int InvokePlace(ModuleName target, int slot, Hand hand, WaferSize size)
  605. {
  606. if (CheckToPostMessage((int)MSG.Place, target, slot, hand, size))
  607. return (int)MSG.Place;
  608. return (int)FSM_MSG.NONE;
  609. }
  610. public int InvokePickAndPlace(ModuleName targetModule, Hand pickHand, int pickSlot, Hand placeHand, int placeSlot, WaferSize size)
  611. {
  612. if (CheckToPostMessage((int)MSG.Swap, targetModule, pickSlot, pickHand, placeHand, placeSlot, size))
  613. return (int)MSG.Swap;
  614. return (int)FSM_MSG.NONE;
  615. }
  616. public int InvokeMap(string target )
  617. {
  618. if (CheckToPostMessage((int)MSG.Map, target ))
  619. return (int)MSG.Map;
  620. return (int)FSM_MSG.NONE;
  621. }
  622. public int InvokeFlip(Hand hand)
  623. {
  624. if (CheckToPostMessage((int)MSG.Flip, hand))
  625. return (int)MSG.Flip;
  626. return (int)FSM_MSG.NONE;
  627. }
  628. public int InvokeSignalTower(LightType type, LightStatus status)
  629. {
  630. if(CheckToPostMessage((int)MSG.Light, type, status))
  631. return (int)MSG.Light;
  632. return (int)FSM_MSG.NONE;
  633. }
  634. public bool IsPrepareTransferReady(ModuleName module, EnumTransferType type, int slot)
  635. {
  636. //if (type == EnumTransferType.Pick)
  637. //{
  638. // //需要补充:判断LP 放好了,而且已经map过。
  639. // return _efem[module].HasCassette && _efem[module].IsMapped;
  640. //}
  641. //else if (type == EnumTransferType.Place)
  642. //{
  643. // //需要补充:判断LP 放好了,而且已经map过。
  644. // return _efem[module].HasCassette && _efem[module].IsMapped;
  645. //}
  646. return false;
  647. }
  648. internal bool CheckReadyRunNewJob(ModuleName module)
  649. {
  650. //???
  651. return true;
  652. }
  653. internal bool CheckReadyTransfer(ModuleName module)
  654. {
  655. //return _efem[module].HasCassette && _efem[module].IsMapped;
  656. return true;
  657. }
  658. internal bool CheckPlaced(ModuleName module)
  659. {
  660. //return _efem[module].HasCassette;
  661. return true;
  662. }
  663. internal void NoteJobStart(ModuleName module)
  664. {
  665. //_efem[module].NoteJobStart();
  666. }
  667. internal void NoteJobComplete(ModuleName module)
  668. {
  669. //_efem[module].NoteJobComplete();
  670. }
  671. private void _debugRoutine()
  672. {
  673. int flag = 0;
  674. // Test Home routine
  675. if (flag == 1)
  676. {
  677. PostMsg(MSG.HomeAll);
  678. }
  679. else if (flag == 2)
  680. {
  681. WaferManager.Instance.CreateWafer(ModuleName.Aligner1, 0, WaferStatus.Normal);
  682. WaferManager.Instance.DeleteWafer(ModuleName.EfemRobot, 0);
  683. var item = new MoveItem(ModuleName.Aligner1, 0, ModuleName.EfemRobot, 0, Hand.Blade1);
  684. var items = new Queue<MoveItem>();
  685. items.Enqueue(item);
  686. PostMsg(MSG.Pick, items);
  687. }
  688. else if (flag == 3)
  689. {
  690. var item = new MoveItem( ModuleName.EfemRobot, 0, ModuleName.Aligner1, 0, Hand.Blade1);
  691. var items = new Queue<MoveItem>();
  692. items.Enqueue(item);
  693. PostMsg(MSG.Place, items);
  694. }
  695. else if (flag == 4)
  696. {
  697. WaferManager.Instance.CreateWafer(ModuleName.LLA, 0, WaferStatus.Normal);
  698. WaferManager.Instance.CreateWafer(ModuleName.LLA, 1, WaferStatus.Normal);
  699. WaferManager.Instance.DeleteWafer(ModuleName.LLA, 2);
  700. WaferManager.Instance.DeleteWafer(ModuleName.LLA, 3);
  701. WaferManager.Instance.CreateWafer(ModuleName.EfemRobot, 0, WaferStatus.Normal);
  702. WaferManager.Instance.CreateWafer(ModuleName.EfemRobot, 1, WaferStatus.Normal);
  703. var item = new MoveItem(ModuleName.EfemRobot, 0, ModuleName.LLA, 2, Hand.Blade1);
  704. var items = new Queue<MoveItem>();
  705. items.Enqueue(item);
  706. item = new MoveItem(ModuleName.EfemRobot, 1, ModuleName.LLA, 3, Hand.Blade2);
  707. items.Enqueue(item);
  708. item = new MoveItem(ModuleName.LLA, 0, ModuleName.EfemRobot, 0, Hand.Blade1);
  709. items.Enqueue(item);
  710. item = new MoveItem(ModuleName.LLA, 1, ModuleName.EfemRobot, 1, Hand.Blade2);
  711. items.Enqueue(item);
  712. PostMsg(MSG.Swap, items);
  713. }
  714. else if (flag == 5)
  715. {
  716. PostMsg(MSG.HomeRB);
  717. }
  718. else if (flag == 6)
  719. {
  720. PostMsg(MSG.HomeAL, ModuleName.Aligner1);
  721. }
  722. else if (flag == 8)
  723. {
  724. OP.DoOperation("LP1.Load");
  725. }
  726. else if(flag == 9)
  727. {
  728. OP.DoOperation("LP1.Unload");
  729. }
  730. }
  731. }
  732. /// <summary>
  733. /// LP entity
  734. /// </summary>
  735. class LoadportEntity : Entity, IEntity
  736. {
  737. private enum STATE
  738. {
  739. Unknown,
  740. Idle, // 1
  741. Initializing, // 2
  742. Initialized, // 3
  743. Mapping, // 4
  744. Mapped, // 5
  745. }
  746. public enum MSG
  747. {
  748. Home, // 0
  749. Map, // 1
  750. ActionDone, // 2
  751. RecHwMsg, // 3
  752. Recover, // 4
  753. Abort, // 5
  754. Online, // 6
  755. Error // 7
  756. }
  757. private readonly EfemBase _efem;
  758. private ModuleName Module { get; }
  759. public LoadportEntity(ModuleName mod, EfemBase efem)
  760. {
  761. this.Module = mod;
  762. _efem = efem;
  763. InitFsmMap();
  764. OP.Subscribe($"{Module}.Home", (cmd, args) => { PostMsg(MSG.Home); return true; });
  765. OP.Subscribe($"{Module}.Abort", (cmd, args) => { PostMsg(MSG.Abort); return true; });
  766. //OP.Subscribe($"{Module}.Map", (cmd, args) => { PostMsg(MSG.Map); return true; });
  767. OP.Subscribe($"{Module}.Online", (cmd, args) => { PostMsg(MSG.Online); return true; });
  768. DATA.Subscribe($"{Module}.Status", () => ((STATE)fsm.State).ToString());
  769. DATA.Subscribe($"{Module}.FsmState", () => ((STATE)fsm.State).ToString());
  770. DATA.Subscribe($"{Module}.FsmPrevState", () => ((STATE)fsm.PrevState).ToString());
  771. DATA.Subscribe($"{Module}.FsmLastMessage", GetFsmLastMessage);
  772. }
  773. private string GetFsmLastMessage()
  774. {
  775. int msg = fsm.LastMsg;
  776. if (msg >= (int)MSG.Home && msg <= (int)MSG.Error)
  777. return ((MSG)msg).ToString();
  778. if (msg == (int)FSM_MSG.TIMER)
  779. return "Timer";
  780. return msg.ToString();
  781. }
  782. private void InitFsmMap()
  783. {
  784. fsm = new StateMachine<LoadportEntity>($"LPM_{Module}", (int)STATE.Idle, 500);
  785. AnyStateTransition(FSM_MSG.TIMER, fnMonitor, FSM_STATE.SAME);
  786. //AnyStateTransition(MSG.RecHwMsg, fnRecMsg, FSM_STATE.SAME);
  787. AnyStateTransition(MSG.Online, fnOnline, FSM_STATE.SAME);
  788. AnyStateTransition(MSG.Recover, fnRecover, STATE.Idle);
  789. AnyStateTransition(MSG.Abort, fnRecover, STATE.Idle);
  790. EnterExitTransition<STATE, FSM_MSG>(STATE.Initializing, fnEnterExecute, FSM_MSG.NONE, fnExitExecute);
  791. // Home
  792. AnyStateTransition(MSG.Home, fnHome, STATE.Initializing);
  793. Transition(STATE.Initializing, MSG.ActionDone, fnActionDone, STATE.Idle);
  794. }
  795. private bool fnOnline(object[] param)
  796. {
  797. bool online = (bool)param[0];
  798. //_efem.SetOnline(Module, online);
  799. return true;
  800. }
  801. private bool fnRecover(object[] param)
  802. {
  803. return true;
  804. }
  805. private bool fnMonitor(object[] param)
  806. {
  807. STATE curSt = (STATE)fsm.State;
  808. if (curSt == STATE.Initializing || curSt == STATE.Mapping)
  809. {
  810. if (fsm.ElapsedTime > 20 * 1000)
  811. {
  812. PostMsg(MSG.Recover);
  813. }
  814. }
  815. return true;
  816. }
  817. private bool fnEnterExecute(object[] param)
  818. {
  819. return true;
  820. }
  821. private bool fnExitExecute(object[] param)
  822. {
  823. return true;
  824. }
  825. private bool fnActionDone(object[] param)
  826. {
  827. return true;
  828. }
  829. private bool fnHome(object[] param)
  830. {
  831. _efem.Home(Module);
  832. return true;
  833. }
  834. public bool Check(int msg, out string reason, params object[] args)
  835. {
  836. throw new NotImplementedException();
  837. }
  838. }
  839. public class EfemSignalTower
  840. {
  841. private EfemBase _efem;
  842. private Queue<KeyValuePair<LightType, LightStatus>> _pendingCmds = new Queue<KeyValuePair<LightType, LightStatus>>();
  843. public EfemSignalTower(EfemBase efem)
  844. {
  845. _efem = efem;
  846. }
  847. public void Monitor()
  848. {
  849. if(Singleton<RouteManager>.Instance.EFEM.RobotStatus != RState.Running && _pendingCmds.Count > 0)
  850. {
  851. var lightCommand = _pendingCmds.Dequeue();
  852. _efem.SetLamp(lightCommand.Key, lightCommand.Value);
  853. }
  854. }
  855. public void SetLight(LightType type, LightStatus status)
  856. {
  857. _pendingCmds.Enqueue(new KeyValuePair<LightType, LightStatus>(type, status));
  858. }
  859. }
  860. }