Sfoglia il codice sorgente

develop autycylce/manualmove module.

sangwq 1 anno fa
parent
commit
ff17e9c447

+ 11 - 5
Venus/Venus_RT/Modules/AutoCycle.cs

@@ -34,7 +34,7 @@ namespace Venus_RT.Modules
         Stop,
     }
 
-    enum MovingStatus
+    public enum MovingStatus
     {
         Staying,
         Waiting,
@@ -110,6 +110,12 @@ namespace Venus_RT.Modules
             _LLASlotNumber = SC.GetValue<int>("LLA.SlotNumber");
             _LLBSlotNumber = SC.GetValue<int>("LLB.SlotNumber");
 
+            _LLAInSlot.RemoveAll(item => item >= _LLASlotNumber);
+            _LLAOutSlot.RemoveAll(item => item >= _LLASlotNumber);
+
+            _LLBInSlot.RemoveAll(item => item >= _LLBSlotNumber);
+            _LLBOutSlot.RemoveAll(item => item >= _LLBSlotNumber);
+
             DATA.Subscribe("Scheduler.CycledCount", () => _cycledCount);
             DATA.Subscribe("Scheduler.CycledWafer", () => _cycledWafer);
             DATA.Subscribe("Scheduler.CycleSetPoint", () => _cycleSetPoint);
@@ -494,12 +500,12 @@ namespace Venus_RT.Modules
                 {
                     if(ModuleHelper.IsLoadPort(module))
                     {
-                        _atmSchedulers[module] = new SchedulerLoadPort(module);
+                        _atmSchedulers[module] = Singleton<TransferModule>.Instance.GetScheduler(module);
                         _atmModules[module] = new ModuleFlag(ModulePriority.Middle);
                     }
                     else if(ModuleHelper.IsAligner(module) || ModuleHelper.IsCooling(module))
                     {
-                        _atmSchedulers[module] = new SchedulerAligner(module);
+                        _atmSchedulers[module] = Singleton<TransferModule>.Instance.GetScheduler(module);
                         _atmModules[module] = new ModuleFlag(ModulePriority.Middle);
                     }
                 }
@@ -510,7 +516,7 @@ namespace Venus_RT.Modules
             {
                 if (ModuleHelper.IsInstalled(module))
                 {
-                    _vacSchedulers[module] = new SchedulerPM(module);
+                    _vacSchedulers[module] = Singleton<TransferModule>.Instance.GetScheduler(module);
                     _vacModules[module] = new ModuleFlag(ModulePriority.Middle);
                 }
             }
@@ -519,7 +525,7 @@ namespace Venus_RT.Modules
             {
                 if (ModuleHelper.IsInstalled(module))
                 {
-                    var llScheduler = new SchedulerLoadLock(module);
+                    var llScheduler = Singleton<TransferModule>.Instance.GetScheduler(module);
                     _vacSchedulers[module] = llScheduler;
                     _vacModules[module] = new ModuleFlag(ModulePriority.Middle);
 

+ 365 - 0
Venus/Venus_RT/Modules/ManualTransfer.cs

@@ -0,0 +1,365 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using Aitex.Core.Common;
+using Aitex.Core.RT.Routine;
+using Aitex.Core.RT.SCCore;
+using Aitex.Sorter.Common;
+using Aitex.Core.RT.Log;
+using Aitex.Core.Util;
+using Aitex.Core.RT.DataCenter;
+using Aitex.Core.RT.RecipeCenter;
+using Aitex.Core.RT.Fsm;
+
+using MECF.Framework.Common.Jobs;
+using MECF.Framework.Common.Routine;
+using MECF.Framework.Common.Equipment;
+using MECF.Framework.Common.SubstrateTrackings;
+using MECF.Framework.Common.Schedulers;
+using MECF.Framework.Common.DBCore;
+
+using Venus_Core;
+
+using Venus_RT.Modules.Schedulers;
+using Venus_RT.Scheduler;
+
+namespace Venus_RT.Modules
+{
+    public class ManualTransfer : IRoutine
+    {
+        SchedulerTMRobot _tmRobot = new SchedulerTMRobot();
+        SchedulerEfemRobot _efemRobot = new SchedulerEfemRobot();
+
+        private Queue<MoveItem> _moveTaskQueue = new Queue<MoveItem>();
+        private MoveItem _move_item = new MoveItem(ModuleName.System, 0, ModuleName.System, 0, Hand.None);
+        private MoveItem _current_item = new MoveItem(ModuleName.System, 0, ModuleName.System, 0, Hand.None);
+
+        private Guid _wafer_id;
+        private R_TRIG _wafer_arrive_trig = new R_TRIG();
+        private MovingStatus _moving_status = MovingStatus.Staying;
+
+        public RState Start(params object[] objs)
+        {
+            // RESET
+            _moveTaskQueue.Clear();
+            _moving_status = MovingStatus.Staying;
+            _wafer_arrive_trig.RST = true ;
+
+            _move_item.SourceModule = (ModuleName)objs[0];
+            _move_item.SourceSlot = (int)objs[1];
+            _move_item.DestinationModule = (ModuleName)objs[2];
+            _move_item.DestinationSlot = (int)objs[3];
+
+            _wafer_id = WaferManager.Instance.GetWafer(_move_item.SourceModule, _move_item.SourceSlot).InnerId;
+
+            if(IsCrossTransfer(_move_item))
+            {
+                var slot = SelectLLFreeSlot();
+                if (slot.Module == ModuleName.System)
+                    return RState.Failed;
+
+                // vac to atm
+                if (ModuleHelper.IsPm(_move_item.SourceModule) || ModuleHelper.IsTMRobot(_move_item.SourceModule))
+                {
+                    _moveTaskQueue.Enqueue(new MoveItem(_move_item.SourceModule, _move_item.SourceSlot, slot.Module, slot.Slot, Hand.Blade1));
+                    if(ModuleHelper.IsEFEMRobot(_move_item.DestinationModule))
+                    {
+                        _moveTaskQueue.Enqueue(new MoveItem(slot.Module, slot.Slot, _move_item.DestinationModule, _move_item.DestinationSlot, (Hand)_move_item.DestinationSlot));
+
+                    }
+                    else
+                    {
+                        Hand hand = SelectEfemRobotFreeHand();
+                        if(hand == Hand.None)
+                        {
+                            LOG.Write(eEvent.WARN_ROUTER, ModuleName.EfemRobot, "No free efem robot arm for wafer move.");
+                            return RState.Failed;
+                        }
+                        _moveTaskQueue.Enqueue(new MoveItem(slot.Module, slot.Slot, ModuleName.EfemRobot, (int)hand, hand));
+                        _moveTaskQueue.Enqueue(new MoveItem(ModuleName.EfemRobot, (int)hand, _move_item.DestinationModule, _move_item.DestinationSlot, hand));
+                    }
+                }
+                // atm to vac
+                else
+                {
+                    if (ModuleHelper.IsEFEMRobot(_move_item.SourceModule))
+                    {
+                        _moveTaskQueue.Enqueue(new MoveItem(_move_item.SourceModule, _move_item.SourceSlot, slot.Module, slot.Slot, (Hand)_move_item.SourceSlot));
+                    }
+                    else
+                    {
+                        Hand hand = SelectEfemRobotFreeHand();
+                        if (hand == Hand.None)
+                        {
+                            LOG.Write(eEvent.WARN_ROUTER, ModuleName.EfemRobot, "No free efem robot arm for wafer move.");
+                            return RState.Failed;
+                        }
+                        _moveTaskQueue.Enqueue(new MoveItem(_move_item.SourceModule, _move_item.SourceSlot, ModuleName.EfemRobot, (int)hand, hand));
+                        _moveTaskQueue.Enqueue(new MoveItem(ModuleName.EfemRobot, (int)hand, slot.Module, slot.Slot, hand));
+                    }
+
+                    _moveTaskQueue.Enqueue(new MoveItem(slot.Module, slot.Slot, _move_item.DestinationModule, _move_item.DestinationSlot, Hand.Blade1));
+                }
+            }
+            else if(IsVacTransfer(_move_item))
+            {
+                _moveTaskQueue.Enqueue(_move_item);
+            }
+            else // atm transfer
+            {
+                if(ModuleHelper.IsEFEMRobot(_move_item.SourceModule))
+                {
+                    _moveTaskQueue.Enqueue(new MoveItem(_move_item.SourceModule, _move_item.SourceSlot, _move_item.DestinationModule, _move_item.DestinationSlot, (Hand)_move_item.SourceSlot));
+                }
+                else if (ModuleHelper.IsEFEMRobot(_move_item.DestinationModule))
+                {
+                    _moveTaskQueue.Enqueue(new MoveItem(_move_item.SourceModule, _move_item.SourceSlot, _move_item.DestinationModule, _move_item.DestinationSlot, (Hand)_move_item.DestinationSlot));
+                }
+                else
+                {
+                    Hand hand = SelectEfemRobotFreeHand();
+                    if (hand == Hand.None)
+                    {
+                        LOG.Write(eEvent.WARN_ROUTER, ModuleName.EfemRobot, "No free efem robot arm for wafer move.");
+                        return RState.Failed;
+                    }
+                    _moveTaskQueue.Enqueue(new MoveItem(_move_item.SourceModule, _move_item.SourceSlot, ModuleName.EfemRobot, (int)hand, hand));
+                    _moveTaskQueue.Enqueue(new MoveItem(ModuleName.EfemRobot, (int)hand, _move_item.DestinationModule, _move_item.DestinationSlot, hand));
+                }
+            }
+
+            _current_item = _moveTaskQueue.Dequeue();
+            _moving_status = MovingStatus.Waiting;
+            return RState.Running;
+        }
+
+        public RState Monitor()
+        {
+            return MoveWaferForward();
+        }
+
+        public void Abort()
+        {
+
+        }
+
+        private RState MoveWaferForward()
+        {
+            switch(_moving_status)
+            {
+                case MovingStatus.Waiting:
+                    {
+                        if(IsCurrentModuleReady())
+                        {
+                            // Post current item
+                            if(IsVacTransfer(_current_item))
+                            {
+                                _tmRobot.PostMoveItems(new MoveItem[1] { _current_item });
+                            }
+                            else
+                            {
+                                _efemRobot.PostMoveItems(new MoveItem[1] { _current_item });
+                            }
+
+                            _moving_status = MovingStatus.Moving;
+                        }
+                    }
+                    break;
+                case MovingStatus.Moving:
+                    {
+                        _wafer_arrive_trig.CLK = IsArriveCurrentTarget();
+                        if (_wafer_arrive_trig.Q)
+                        {
+                            _moving_status = MovingStatus.Staying;
+                        }
+                    }
+                    break;
+                case MovingStatus.Staying:
+                    {
+                        if(IsCurrentModuleReady())
+                        {
+                            if(_moveTaskQueue.Count > 0)
+                            {
+                                _current_item = _moveTaskQueue.Dequeue();
+                                _moving_status = MovingStatus.Waiting;
+                            }
+                        }
+                        break;
+                    }
+            }
+
+            return TransferStatus();
+        }
+
+        private bool IsVacTransfer(MoveItem item)
+        {
+            return ModuleHelper.IsPm(item.SourceModule) || 
+                ModuleHelper.IsTMRobot(item.SourceModule) || 
+                ModuleHelper.IsPm(item.DestinationModule) || 
+                ModuleHelper.IsTMRobot(item.DestinationModule);
+        }
+
+        private bool IsCrossTransfer(MoveItem item)
+        {
+            if (ModuleHelper.IsLoadLock(item.DestinationModule) || ModuleHelper.IsLoadLock(item.SourceModule))
+                return false;
+
+            if (((ModuleHelper.IsPm(item.SourceModule) || ModuleHelper.IsTMRobot(item.SourceModule)) &&
+                !ModuleHelper.IsPm(item.DestinationModule) && !ModuleHelper.IsTMRobot(item.DestinationModule)) ||
+                ((ModuleHelper.IsPm(item.DestinationModule) || ModuleHelper.IsTMRobot(item.DestinationModule)) &&
+                !ModuleHelper.IsPm(item.SourceModule) && !ModuleHelper.IsTMRobot(item.SourceModule)))
+                return true;
+
+            return false;
+        }
+
+        private bool IsArriveCurrentTarget()
+        {
+            var wafer = WaferManager.Instance.GetWafer(_current_item.DestinationModule, _current_item.DestinationSlot);
+            return !wafer.IsEmpty && wafer.InnerId == _wafer_id;
+        }
+
+        private bool IsCurrentModuleReady()
+        {
+            return (IsVacTransfer(_current_item) ? _tmRobot.IsAvailable : _efemRobot.IsAvailable) && 
+                _isModuleReady(_current_item.SourceModule) && 
+                _isModuleReady(_current_item.DestinationModule);
+        }
+
+        private bool IsTransferError()
+        {
+            return (IsVacTransfer(_current_item) ? _tmRobot.IsError : _efemRobot.IsError) ||
+                _isModuleError(_current_item.SourceModule) ||
+                _isModuleError(_current_item.DestinationModule);
+        }
+
+        private bool _isModuleReady(ModuleName module)
+        {
+            return Singleton<TransferModule>.Instance.GetScheduler(module).IsAvailable;
+        }
+
+        private bool _isModuleError(ModuleName module)
+        {
+            return Singleton<TransferModule>.Instance.GetScheduler(module).IsError;
+        }
+
+        private Hand SelectEfemRobotFreeHand()
+        {
+            if (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 0))
+                return Hand.Blade1;
+            else if (WaferManager.Instance.CheckNoWafer(ModuleName.EfemRobot, 1))
+                return Hand.Blade2;
+            else
+                return Hand.None;
+        }
+
+        private SlotItem SelectLLFreeSlot()
+        {
+            foreach(var ll in new ModuleName[2] { ModuleName.LLA, ModuleName.LLB})
+            {
+                if (ModuleHelper.IsInstalled(ll) && _isModuleReady(ll))
+                {
+                    for (int i = 0; i < 4; i++)
+                    {
+                        if (WaferManager.Instance.CheckNoWafer(ll, i))
+                            return new SlotItem(ll, i);
+                    }
+                }
+            }
+
+            LOG.Write(eEvent.WARN_ROUTER, ModuleName.System, "Cannot move wafer as no valid Loadlock slot");
+            return new SlotItem(ModuleName.System, -1);
+        }
+
+        private RState TransferStatus()
+        {
+            if (IsTransferError())
+                return RState.Failed;
+
+            if (IsCurrentModuleReady() && _moveTaskQueue.Count == 0 && _moving_status == MovingStatus.Staying)
+                return RState.End;
+
+            return RState.Running;
+        }
+    }
+
+    public class ReturnAllWafer : IRoutine
+    {
+        private List<ModuleName> _moduleList = new List<ModuleName> { ModuleName.EfemRobot, ModuleName.Aligner1, ModuleName.Aligner, ModuleName.LLA, ModuleName.LLB, ModuleName.TMRobot, ModuleName.PMA, ModuleName.PMB, ModuleName.PMC, ModuleName.PMD };
+        private ManualTransfer _manualTransfer;
+        private Queue<MoveItem> _returnTaskQueue = new Queue<MoveItem>();
+        private MoveItem _current_item;
+        public ReturnAllWafer(ManualTransfer manualTransfer)
+        {
+            _manualTransfer = manualTransfer;
+        }
+
+        public RState Start(params object[] objs)
+        {
+            foreach(var mod in _moduleList)
+            {
+                if (ModuleHelper.IsInstalled(mod) && Singleton<TransferModule>.Instance.GetScheduler(mod).IsAvailable)
+                {
+                    PushWaferToReturnQueqe(mod, 0);
+                    if (ModuleHelper.IsEFEMRobot(mod) || ModuleHelper.IsTMRobot(mod))
+                    {
+                        PushWaferToReturnQueqe(mod, 1);
+                    }
+                    else if (ModuleHelper.IsLoadLock(mod))
+                    {
+                        int nSlotNumber = SC.GetValue<int>($"{mod}.SlotNumber");
+                        for (int i = 1; i < nSlotNumber; i++)
+                        {
+                            PushWaferToReturnQueqe(mod, i);
+                        }
+                    }
+                }
+            }
+
+            if (_returnTaskQueue.Count == 0)
+                return RState.Failed;
+
+            _current_item = _returnTaskQueue.Dequeue();
+            _manualTransfer.Start(_current_item.SourceModule, _current_item.SourceSlot, _current_item.DestinationModule, _current_item.DestinationSlot);
+            return RState.Running;
+        }
+
+        public RState Monitor()
+        {
+            var ret = _manualTransfer.Monitor();
+            if (ret == RState.End)
+            {
+                if (_returnTaskQueue.Count > 0)
+                {
+                    _current_item = _returnTaskQueue.Dequeue();
+                    _manualTransfer.Start(_current_item.SourceModule, _current_item.SourceSlot, _current_item.DestinationModule, _current_item.DestinationSlot);
+                }
+                else
+                    return RState.End;
+            }
+            else if (ret == RState.Failed || ret == RState.Timeout)
+            {
+                LOG.Write(eEvent.ERR_ROUTINE_FAILED, ModuleName.System, $"Return Wafer {_current_item.SourceModule}{_current_item.SourceSlot} failed");
+                return RState.Failed;
+            }
+
+
+            return RState.Running;
+        }
+
+        public void Abort()
+        {
+
+        }
+
+        private void PushWaferToReturnQueqe(ModuleName mod, int nSlot)
+        {
+            var wafer = WaferManager.Instance.GetWafer(mod, nSlot);
+            if (!wafer.IsEmpty)
+            {
+                _returnTaskQueue.Enqueue(new MoveItem(mod, nSlot, (ModuleName)wafer.OriginStation, wafer.OriginSlot, Hand.Blade1));
+            }
+        }
+    }
+}

+ 49 - 9
Venus/Venus_RT/Modules/RouteManager.cs

@@ -124,6 +124,8 @@ namespace Venus_RT.Modules
 
         private TMCycle _TMCycle;
         private AutoCycle _AutoCycle;
+        private ManualTransfer _manualTransfer;
+        private ReturnAllWafer _returnWafer;
 
         private bool _isWaitUnload;
 
@@ -533,6 +535,8 @@ namespace Venus_RT.Modules
 
             _TMCycle = new TMCycle();
             _AutoCycle = new AutoCycle();
+            _manualTransfer = new ManualTransfer();
+            _returnWafer = new ReturnAllWafer(_manualTransfer);
 
             BuildTransitionTable();
             return true;
@@ -595,6 +599,16 @@ namespace Venus_RT.Modules
             Transition(RtState.AutoIdle,        MSG.AbortJob,           FsmAbortJob,                RtState.AutoIdle);
             Transition(RtState.AutoIdle,        MSG.Map,                FsmMap,                     RtState.AutoIdle);
 
+            //Transfer 
+            Transition(RtState.Idle,            MSG.MoveWafer,          FsmStartTransfer,           RtState.Transfer);
+            Transition(RtState.Transfer,        FSM_MSG.TIMER,          FsmMonitorTransfer,         RtState.Idle);
+            Transition(RtState.Transfer,        MSG.ABORT,              FsmAbort,                   RtState.Idle);
+
+            //Return Wafer 
+            Transition(RtState.Idle,            MSG.ReturnAllWafer,     FsmStartReturnWafer,        RtState.ReturnWafer);
+            Transition(RtState.ReturnWafer,     FSM_MSG.TIMER,          FsmMonitorReturnWafer,      RtState.Idle);
+            Transition(RtState.ReturnWafer,     MSG.ABORT,              FsmAbort,                   RtState.Idle);
+
         }
 
         private bool FsmMonitor(object[] objs)
@@ -757,6 +771,40 @@ namespace Venus_RT.Modules
             return true;
         }
 
+        private bool FsmStartTransfer(object[] objs)
+        {
+            return _manualTransfer.Start(objs) == RState.Running;
+        }
+
+        private bool FsmMonitorTransfer(object[] objs)
+        {
+            RState ret = _manualTransfer.Monitor();
+            if (ret == RState.Failed || ret == RState.Timeout)
+            {
+                PostMsg(MSG.ERROR);
+                return false;
+            }
+
+            return ret == RState.End;
+        }
+
+        private bool FsmStartReturnWafer(object[] objs)
+        {
+            return _returnWafer.Start(objs) == RState.Running;
+        }
+
+        private bool FsmMonitorReturnWafer(object[] objs)
+        {
+            RState ret = _returnWafer.Monitor();
+            if (ret == RState.Failed || ret == RState.Timeout)
+            {
+                PostMsg(MSG.ERROR);
+                return false;
+            }
+
+            return ret == RState.End;
+        }
+
         private bool FsmMap(object[] objs)
         {
             return true;
@@ -817,15 +865,7 @@ namespace Venus_RT.Modules
             }
             else if (flag == 4)
             {
-                Dictionary<string, object> param = new Dictionary<string, object>()
-                {
-                    {"JobId",  "CJ_Local_LP1"},
-                    {"Module", "LP1"},
-                    {"SlotSequence", new List<string>(){ "333333", "333333", "333333", "333333", "333333", "333333", "333333", "333333", "333333", "333333", "333333", "333333", "333333","333333", "333333", "333333", "333333", "333333", "333333", "333333", "333333", "333333", "333333", "333333", "333333" }.ToArray() },
-                    {"AutoStart", false},
-                };
-
-                OP.DoOperation("System.CreateJob", param);
+                PostMsg(MSG.ReturnAllWafer);
             }
             else if(flag == 5)
             {

+ 1 - 1
Venus/Venus_RT/Modules/Schedulers/SchedulerLoadLock.cs

@@ -14,7 +14,7 @@ using Venus_RT.Scheduler;
 
 namespace Venus_RT.Modules.Schedulers
 {
-    class SchedulerLoadLock : SchedulerModule
+    public class SchedulerLoadLock : SchedulerModule
     {
         public override bool IsAvailable
         {

+ 20 - 5
Venus/Venus_RT/Modules/Schedulers/SchedulerTMRobot.cs

@@ -23,7 +23,7 @@ namespace Venus_RT.Modules.Schedulers
         public Queue<MoveItem> moveList { get;  set; }
 
     }
-    class SchedulerTMRobot : SchedulerModule
+    public class SchedulerTMRobot : SchedulerModule
     {
         public override bool IsAvailable
         {
@@ -226,7 +226,7 @@ namespace Venus_RT.Modules.Schedulers
             {
                 foreach(var moveItem in items)
                 {
-                    if(!ModuleHelper.IsTMRobot(moveItem.SourceModule))
+                    if(!ModuleHelper.IsTMRobot(moveItem.SourceModule) && !ModuleHelper.IsTMRobot(moveItem.DestinationModule))
                     {
                         SchedulerItem item = new SchedulerItem();
                         item.MoveType = ModuleHelper.IsLoadLock(moveItem.SourceModule) ?  TMEntity.MSG.Pick : TMEntity.MSG.PMPick;
@@ -234,15 +234,30 @@ namespace Venus_RT.Modules.Schedulers
                         item.moveList = new Queue<MoveItem>();
                         item.moveList.Enqueue(new MoveItem(moveItem.SourceModule, moveItem.SourceSlot, ModuleName.TMRobot, (int)freeHand, freeHand));
                         _schedulerList.Enqueue(item);
-                    }
 
-                    if (!ModuleHelper.IsTMRobot(moveItem.DestinationModule))
+                        item = new SchedulerItem();
+                        item.MoveType = ModuleHelper.IsLoadLock(moveItem.DestinationModule) ? TMEntity.MSG.Place : TMEntity.MSG.PMPlace;
+                        item.target = moveItem.DestinationModule;
+                        item.moveList = new Queue<MoveItem>();
+                        item.moveList.Enqueue(new MoveItem(ModuleName.TMRobot, (int)freeHand, moveItem.DestinationModule, moveItem.DestinationSlot, freeHand));
+                        _schedulerList.Enqueue(item);
+                    }
+                    else if(ModuleHelper.IsTMRobot(moveItem.SourceModule))
                     {
                         SchedulerItem item = new SchedulerItem();
                         item.MoveType = ModuleHelper.IsLoadLock(moveItem.DestinationModule) ? TMEntity.MSG.Place : TMEntity.MSG.PMPlace;
                         item.target = moveItem.DestinationModule;
                         item.moveList = new Queue<MoveItem>();
-                        item.moveList.Enqueue(new MoveItem(ModuleName.TMRobot, (int)freeHand, moveItem.DestinationModule, moveItem.DestinationSlot,  freeHand));
+                        item.moveList.Enqueue(new MoveItem(ModuleName.TMRobot, moveItem.SourceSlot, moveItem.DestinationModule, moveItem.DestinationSlot, (Hand)moveItem.SourceSlot));
+                        _schedulerList.Enqueue(item);
+                    }
+                    else if(ModuleHelper.IsTMRobot(moveItem.DestinationModule))
+                    {
+                        SchedulerItem item = new SchedulerItem();
+                        item.MoveType = ModuleHelper.IsLoadLock(moveItem.SourceModule) ? TMEntity.MSG.Pick : TMEntity.MSG.PMPick;
+                        item.target = moveItem.SourceModule;
+                        item.moveList = new Queue<MoveItem>();
+                        item.moveList.Enqueue(new MoveItem(moveItem.SourceModule, moveItem.SourceSlot, ModuleName.TMRobot, moveItem.DestinationSlot, (Hand)moveItem.DestinationSlot));
                         _schedulerList.Enqueue(item);
                     }
                 }

+ 28 - 2
Venus/Venus_RT/Modules/Schedulers/TransferModule.cs

@@ -9,9 +9,14 @@ namespace Venus_RT.Modules
     public class TransferModule
     {
         protected SchedulerEfemRobot _efemRobot = new SchedulerEfemRobot();
+        protected SchedulerTMRobot _tmRobot = new SchedulerTMRobot();
 
         protected SchedulerLoadPort _lp1 = new SchedulerLoadPort(ModuleName.LP1);
         protected SchedulerLoadPort _lp2 = new SchedulerLoadPort(ModuleName.LP2);
+        protected SchedulerLoadPort _lp3 = new SchedulerLoadPort(ModuleName.LP3);
+
+        protected SchedulerLoadLock _lla = new SchedulerLoadLock(ModuleName.LLA);
+        protected SchedulerLoadLock _llb = new SchedulerLoadLock(ModuleName.LLB);
 
         protected SchedulerAligner _aligner1 = new SchedulerAligner(ModuleName.Aligner1);
         protected SchedulerAligner _aligner2 = new SchedulerAligner(ModuleName.Aligner2);
@@ -21,20 +26,28 @@ namespace Venus_RT.Modules
         protected SchedulerPM _pma = new SchedulerPM(ModuleName.PMA);
         protected SchedulerPM _pmb = new SchedulerPM(ModuleName.PMB);
 
+        protected SchedulerPM _pmc = new SchedulerPM(ModuleName.PMC);
+        protected SchedulerPM _pmd = new SchedulerPM(ModuleName.PMD);
+
         public TransferModule()
         {
 
         }
 
 
-        protected SchedulerModule GetModule(string name)
+        public SchedulerModule GetScheduler(ModuleName module)
         {
-            switch (ModuleHelper.Converter(name))
+            if (!ModuleHelper.IsInstalled(module))
+                return null;
+
+            switch (module)
             {
                 case ModuleName.LP1:
                     return _lp1;
                 case ModuleName.LP2:
                     return _lp2;
+                case ModuleName.LP3:
+                    return _lp3;
 
                 case ModuleName.Aligner1:
                     return _aligner1;
@@ -49,10 +62,23 @@ namespace Venus_RT.Modules
                     return _cooling2;
                 case ModuleName.EfemRobot:
                     return _efemRobot;
+
+                case ModuleName.LLA:
+                    return _lla;
+                case ModuleName.LLB:
+                    return _llb;
+
+                case ModuleName.TMRobot:
+                    return _tmRobot;
+
                 case ModuleName.PMA:
                     return _pma;
                 case ModuleName.PMB:
                     return _pmb;
+                case ModuleName.PMC:
+                    return _pmc;
+                case ModuleName.PMD:
+                    return _pmd;
             }
 
             return null;

+ 1 - 0
Venus/Venus_RT/Venus_RT.csproj

@@ -196,6 +196,7 @@
     <Compile Include="Modules\LPs\LoadPortUnloadRoutine.cs" />
     <Compile Include="Modules\LPs\LoadPortWriteCarrierIdRoutine.cs" />
     <Compile Include="Modules\LPs\LoadPortWriteTagDataRoutine.cs" />
+    <Compile Include="Modules\ManualTransfer.cs" />
     <Compile Include="Modules\PMs\GasBoxLeakCheckRoutine.cs" />
     <Compile Include="Modules\PMs\GasFlowRoutine.cs" />
     <Compile Include="Modules\PMs\LLPickRoutine.cs" />