using Aitex.Core.Common; using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Device; using Aitex.Core.RT.Device.Unit; using Aitex.Core.RT.Event; using Aitex.Core.RT.OperationCenter; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using Aitex.Sorter.Common; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.CarrierIdReaders.CarrierIDReaderBase; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts.TDK; using System; using System.Collections.Generic; using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts.LoadPortBase; using static Aitex.Core.RT.Device.Unit.IOE84Passive; namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.LoadPorts { public enum IndicatorType { Load, Unload, Presence, Placement, Alarm, AccessManual, AccessAuto, Status1, Status2, Manual, Auto, Reserve, Error, Access, Busy, Complete, } public enum E84PioPosition { Floor = 0, Middle = 1, Overhead = 2 } public enum E84PioSignalAtoP { VALID = 1, CS_0 = 2, CS_1 = 3, TR_REQ = 4, BUSY = 5, COMPT = 6, CONT = 7, AM_AVBL = 8 } public enum E84PioSignalPtoA { L_REQ = 11, U_REQ = 12, READY = 13, HO_AVBL = 14, ES = 15, VA = 16, VS_0 = 17, VS_1 = 18 } public interface IE87CallBack { void CarrierArrive(); void CarrerRemove(string carrierID); void CarrierIDReadSuccess(string carrierID); void CarrierIDReadFail(); void MappingComplete(string carrierID, string slotmap); void LoadportError(string errorcode); void LoadComplete(); void UnloadComplete(); void OnLPHomed(); void OnE84HandoffStart(bool isload); void OnE84HandoffComplete(bool isload); } public interface IE84CallBack { void SetHoAutoControl(bool value); void SetHoAvailable(bool value); void SetE84SignalState(E84PassiveSignal signal, bool value); bool GetE84SignalState(E84SignalID signal); void SetFoupStatus(bool foupon); void SetReadyTransferStatus(bool ready); void Stop(); void Reset(); void ResetE84(); void Complete(); event Action OnE84HandOffStart; event Action OnE84HandOffComplete; event Action OnE84HandOffTimeout; event Action OnE84ActiveSignalChange; event Action OnE84PassiveSignalChange; } public abstract class LoadPort : BaseDevice, ILoadPort { public event Action ActionDone; public IndicatorState IndicatiorLoad { get; set; } public IndicatorState IndicatiorUnload { get; set; } public IndicatorState IndicatiorPresence { get; set; } public IndicatorState IndicatorAlarm { get; set; } public IndicatorState IndicatiorPlacement { get; set; } public IndicatorState IndicatiorOpAccess { get; set; } public IndicatorState IndicatiorAccessAuto { get; set; } public IndicatorState IndicatiorAccessManual { get; set; } public IndicatorState IndicatiorStatus1 { get; set; } public IndicatorState IndicatiorStatus2 { get; set; } public IndicatorState IndicatiorManualMode { get; set; } public IndicatorState IndicatiorClampUnclamp { get; set; } public IndicatorState IndicatiorDockUndock { get; set; } public static Dictionary LoadPortIndicatorLightMap = new Dictionary() { {IndicatorType.Load, Indicator.LOAD}, {IndicatorType.Unload, Indicator.UNLOAD}, {IndicatorType.AccessAuto, Indicator.ACCESSAUTO }, {IndicatorType.AccessManual, Indicator.ACCESSMANUL}, {IndicatorType.Alarm, Indicator.ALARM}, {IndicatorType.Presence, Indicator.PRESENCE}, {IndicatorType.Placement, Indicator.PLACEMENT}, {IndicatorType.Status1, Indicator.RESERVE1}, {IndicatorType.Status2, Indicator.RESERVE2}, }; public IndicatorState[] IndicatorStateFeedback { get; set; } public virtual FoupClampState ClampState { get; set; } public virtual FoupDockState DockState { get; set; } public virtual FoupDoorState DoorState { get; set; } public virtual CasstleType CasstleType { get; set; } public string SlotMap { get { return GetSlotMap(); } } //Hirata public int WaferCount { get; set; } public virtual bool IsBusy { get; set; } public virtual bool IsIdle { get; set; } public virtual bool IsMoving { get; set; } public virtual bool IsInfoPadAOn { get; set; } public virtual bool IsInfoPadBOn { get; set; } public virtual bool IsInfoPadCOn { get; set; } public virtual bool IsInfoPadDOn { get; set; } public virtual bool IsWaferProtrude { get; set; } public virtual bool IsMonitorProtrude { get; set; } = false; public virtual string InfoPadCarrierType { get; set; } = ""; public virtual int InfoPadCarrierIndex { get; set; } = -1; public virtual LoadportCassetteState CassetteState { get; set; } public WaferSize Size { get { IoWaferSizeDetector detector = DEVICE.GetDevice($"{Name}WaferDetector"); if (detector != null) return detector.Value; int carrierIndex = SC.ContainsItem($"CarrierInfo.{Name}CarrierIndex") ? SC.GetValue($"CarrierInfo.{Name}CarrierIndex") : 0; WaferSize wsize = SC.ContainsItem($"CarrierInfo.CarrierWaferSize{carrierIndex}") ? (WaferSize)SC.GetValue($"CarrierInfo.CarrierWaferSize{carrierIndex}") : WaferSize.WS12; return wsize; } } public virtual WaferSize GetCurrentWaferSize() { return Size; } public bool IsMapWaferByLoadPort { get; set; } public EnumLoadPortType PortType { get; set; } public bool Initalized { get; set; } public bool IsPresent { get { return _isPresent; } } public bool IsPlacement { get { return _isPlaced; } } public bool IsMapped { get { return _isMapped; } } public bool IsComplete { get; set; } public bool IsAccessSwPressed { get { return _isAccessSwPressed; } } public bool Error { get; set; } public string ErrorCode { get; set; } public bool MapError { get; set; } public bool ReadCarrierIDError { get; set; } public bool ExecuteError { get; set; } = false; /// /// 是否处于FOSB模式 /// public bool IsFOSBMode { get; set; } public TDKY_AxisPos DockPOS { get; set; } = TDKY_AxisPos.Unknown; public TDKZ_AxisPos DoorPOS { get; set; } = TDKZ_AxisPos.Unknown; public DeviceState State { get { if (!Initalized) { return DeviceState.Unknown; } if (Error || ExecuteError || MapError || ReadCarrierIDError) { return DeviceState.Error; } if (IsBusy) return DeviceState.Busy; return DeviceState.Idle; } } public string CarrierId { get { return _carrierId; } } public string LPLotID { get { return _lplotID; } } public string RfId { get { return _rfid; } } public RD_TRIG PresentTrig { get { return _presentTrig; } } public RD_TRIG PlacedtTrig { get { return _placetTrig; } } public RD_TRIG AccessSwPressedTrig { get { return _accessSwPressedTrig; } } public RD_TRIG ClampedTrig { get { return _clampTrig; } } public RD_TRIG DockTrig { get { return _dockTrig; } } public RD_TRIG DoorTrig { get { return _doorTrig; } } protected bool _isPresent; protected bool _isPlaced; protected bool _isDocked; protected bool _isAccessSwPressed; protected string _carrierId = ""; protected string _rfid; protected string _lplotID; protected bool _isMapped; private ModuleName _module; public ModuleName LPModuleName => _module; //private ModuleStateEnum _state; private readonly RD_TRIG _presentTrig = new RD_TRIG(); private readonly RD_TRIG _placetTrig = new RD_TRIG(); private readonly RD_TRIG _accessSwPressedTrig = new RD_TRIG(); private readonly RD_TRIG _clampTrig = new RD_TRIG(); private readonly RD_TRIG _dockTrig = new RD_TRIG(); private readonly RD_TRIG _doorTrig = new RD_TRIG(); public R_TRIG TrigWaferProtrude = new R_TRIG(); private List> _waferId = new List>(); private int _slotNumber; public string PortId { get; private set; } public string PortCategory { get { return (SC.ContainsItem($"LoadPort.LoadPort{PortId}CarrierLabel") ? SC.GetStringValue($"LoadPort.LoadPort{PortId}CarrierLabel") : ""); } } ModuleName[] PortModuleNames = new[] { ModuleName.LP1,ModuleName.LP2,ModuleName.LP3,ModuleName.LP4,ModuleName.LP5, ModuleName.LP6,ModuleName.LP7,ModuleName.LP8,ModuleName.LP9,ModuleName.LP10, ModuleName.Cassette, ModuleName.CassAL, ModuleName.CassAR, ModuleName.CassBL, ModuleName.CassBR, }; private string EventCarrierArrived = "CARRIER_ARRIVED"; private string EventCarrierIdRead = "CARRIER_ID_READ"; private string EventCarrierIdReadFailed = "CARRIER_ID_READ_FAILED"; private string EventCarrierIdWrite = "CARRIER_ID_WRITE"; private string EventCarrierIdWriteFailed = "CARRIER_ID_WRITE_FAILED"; protected string EventSlotMapAvailable = "SLOT_MAP_AVAILABLE"; private string EventCarrierRemoved = "CARRIER_REMOVED"; private string EventCarrierUnloaded = "CARRIER_UNLOADED"; public string EventCarrierloaded = "CARRIR_DOCK_COMPLETE"; public string EventCarrierClamped = "CCLMP"; public string EventCarrierUnClamped = "CUCLMP"; private string EventLPHomed = "LP_HOMED"; protected string PORT_ID = "PORT_ID"; protected string CAR_ID = "CAR_ID"; protected string SLOT_MAP = "SLOT_MAP"; protected string PORT_CTGRY = "PORT_CTGRY"; protected string RF_ID = "RF_ID"; protected string PORT_CARRIER_TYPE = "PORT_CARRIER_TYPE"; private string EventRfIdRead = "RF_ID_READ"; private string EventRfIdReadFailed = "RF_ID_READ_FAILED"; private string EventRfIdWrite = "RF_ID_WRITE"; private string EventRfIdWriteFailed = "RF_ID_WRITE_FAILED"; public string AlarmLoadPortError { get => _module + "Error"; } public string AlarmLoadPortMappingError { get => _module + "MappingError"; } public string AlarmCarrierIDReadError { get => _module + "CarrierIDReadFail"; } private IE87CallBack _lpcallback = null; public IE87CallBack LPCallBack { get { return _lpcallback; } set { _lpcallback = value; } } private IE84CallBack _lpE84Callback = null; public IE84CallBack LPE84Callback { get { return _lpE84Callback; } set { _lpE84Callback = value; } } private ICarrierIDReader _carrierIDReadercallback = null; public ICarrierIDReader CarrierIDReaderCallBack { get { return _carrierIDReadercallback; } set { _carrierIDReadercallback = value; } } public LoadPort(int slotNumber = 25) { _slotNumber = slotNumber; } public LoadPort(string module, string name, int slotNumber = 25) : base(module, name, name, "") { _slotNumber = slotNumber; } public virtual bool IsAutoClampOnFoupOn { get { if (SC.ContainsItem($"LoadPort.LP{PortId}.AutoClampOnFoupOn")) return SC.GetValue($"LoadPort.LP{PortId}.AutoClampOnFoupOn"); return false; } } public virtual bool Initialize() { for (int i = 0; i < 25; i++) { _waferId.Add(new List() { i.ToString("D2"),"","","" }); } if (!Enum.TryParse(Name, out ModuleName m)) Enum.TryParse(Module, out m); _module = m; if ((int)_module >= 97) PortId = ((int)_module - 96).ToString(); else PortId = ((int)_module).ToString(); DoorState = FoupDoorState.Unknown; WaferManager.Instance.SubscribeLocation(_module, _slotNumber); CarrierManager.Instance.SubscribeLocation(_module.ToString()); DATA.Subscribe(Name, "IsPresent", () => _isPresent); DATA.Subscribe(Name, "IsPlaced", () => _isPlaced); DATA.Subscribe(Name, "IsClamped", () => ClampState == FoupClampState.Close); DATA.Subscribe(Name, "IsDocked", () => DockState == FoupDockState.Docked); DATA.Subscribe(Name, "IsDoorOpen", () => DoorState == FoupDoorState.Open); DATA.Subscribe(Name, "ModuleState", () => "Idle"); DATA.Subscribe(Name, "CarrierId", () => _carrierId); DATA.Subscribe(Name, "LPLotID", () => _lplotID); DATA.Subscribe(Name, "IsMapped", () => _isMapped); DATA.Subscribe($"{Name}.LoadportState", () => State); DATA.Subscribe($"{Name}.LoadportBusy", () => IsBusy); DATA.Subscribe($"{Name}.LoadportError", () => ErrorCode); DATA.Subscribe($"{Name}.CassetteState", () => CassetteState); DATA.Subscribe($"{Name}.FoupClampState", () => ClampState); DATA.Subscribe($"{Name}.FoupDockState", () => DockState); DATA.Subscribe($"{Name}.FoupDoorState", () => DoorState); DATA.Subscribe($"{Name}.SlotMap", () => SlotMap); DATA.Subscribe($"{Name}.IndicatiorLoad", () => IndicatiorLoad); DATA.Subscribe($"{Name}.IndicatiorUnload", () => IndicatiorUnload); DATA.Subscribe($"{Name}.IndicatiorPresence", () => IndicatiorPresence); DATA.Subscribe($"{Name}.IndicatiorPlacement", () => IndicatiorPlacement); DATA.Subscribe($"{Name}.IndicatiorAlarm", () => IndicatorAlarm); DATA.Subscribe($"{Name}.IndicatiorAccessAuto", () => IndicatiorAccessAuto); DATA.Subscribe($"{Name}.IndicatiorAccessManual", () => IndicatiorAccessManual); DATA.Subscribe($"{Name}.IndicatiorOpAccess", () => IndicatiorOpAccess); DATA.Subscribe($"{Name}.IndicatiorStatus1", () => IndicatiorStatus1); DATA.Subscribe($"{Name}.IndicatiorStatus2", () => IndicatiorStatus2); DATA.Subscribe($"{Name}.CasstleType", () => (int)CasstleType); DATA.Subscribe($"{Name}.InfoPadCarrierType", () => InfoPadCarrierType); DATA.Subscribe($"{Name}.InfoPadCarrierIndex", () => InfoPadCarrierIndex); DATA.Subscribe($"{Name}.IsError", () => State == DeviceState.Error); //if (PortStateVariableNames.Length > _lpIndex) // DATA.Subscribe(PortStateVariableNames[_lpIndex], () => (_isPlaced && _isPresent) ? "1" : "0"); //if (PortSlotMapVariableNames.Length > _lpIndex) // DATA.Subscribe(PortSlotMapVariableNames[_lpIndex], () => SlotMap); //if (PortWaferIdVariableNames.Length > _lpIndex) // DATA.Subscribe(PortWaferIdVariableNames[_lpIndex], UpdatedWaferIdList); EV.Subscribe(new EventItem("Event", EventCarrierArrived, "Carrier arrived")); EV.Subscribe(new EventItem("Event", EventCarrierRemoved, "Carrier removed")); EV.Subscribe(new EventItem("Event", EventCarrierIdRead, "Carrier ID read")); EV.Subscribe(new EventItem("Event", EventCarrierIdReadFailed, "Carrier ID read failed")); EV.Subscribe(new EventItem("Event", EventCarrierIdWrite, "Carrier ID write")); EV.Subscribe(new EventItem("Event", EventCarrierIdWriteFailed, "Carrier ID write failed")); EV.Subscribe(new EventItem("Event", EventSlotMapAvailable, "Slot map available")); EV.Subscribe(new EventItem("Event", EventCarrierUnloaded, "Carrier unloaded")); EV.Subscribe(new EventItem("Event", EventCarrierloaded, "Carrier loaded")); EV.Subscribe(new EventItem("Event", EventRfIdRead, "Carrier RFID read")); EV.Subscribe(new EventItem("Event", EventRfIdReadFailed, "Carrier RFID read failed")); EV.Subscribe(new EventItem("Event", EventRfIdWrite, "Carrier RFID write")); EV.Subscribe(new EventItem("Event", EventRfIdWriteFailed, "Carrier RFID write failed")); EV.Subscribe(new EventItem("Event", EventCarrierClamped, "Carrier was clamped.")); EV.Subscribe(new EventItem("Event", EventCarrierUnClamped, "Carrier was unclamped.")); EV.Subscribe(new EventItem("Event", AlarmLoadPortError, $"Load Port {Name}error", EventLevel.Alarm, EventType.EventUI_Notify)); EV.Subscribe(new EventItem("Event", AlarmLoadPortMappingError, $"Load Port {Name} mapping error", EventLevel.Alarm, EventType.EventUI_Notify)); EV.Subscribe(new EventItem("Event", AlarmCarrierIDReadError, $"Load Port {Name} read carrierID error", EventLevel.Alarm, EventType.EventUI_Notify)); //} IsIdle = true; //_state = ModuleStateEnum.Idle; IndicatorStateFeedback = new IndicatorState[20]; if (_lpE84Callback != null) { _lpE84Callback.OnE84ActiveSignalChange += _lpE84Callback_OnE84ActiveSignalChange; _lpE84Callback.OnE84PassiveSignalChange += _lpE84Callback_OnE84PassiveSignalChange; _lpE84Callback.OnE84HandOffComplete += _lpE84Callback_OnE84HandOffComplete; _lpE84Callback.OnE84HandOffStart += _lpE84Callback_OnE84HandOffStart; _lpE84Callback.OnE84HandOffTimeout += _lpE84Callback_OnE84HandOffTimeout; } RegisterOperation(); return true; } private void _lpE84Callback_OnE84PassiveSignalChange(E84SignalID arg2, bool arg3) { ; } private void _lpE84Callback_OnE84HandOffTimeout(E84Timeout arg2, string arg3) { ; } private void _lpE84Callback_OnE84HandOffStart(string arg2) { OnE84HandOffStart(arg2 == "Load"); } private void _lpE84Callback_OnE84HandOffComplete(string arg2) { OnE84HandOffComplete(arg2 == "Load"); } private void _lpE84Callback_OnE84ActiveSignalChange(E84SignalID arg2, bool arg3) { ; } public virtual bool Connect() { return true; } public virtual bool IsAutoReadCarrierID { get { return SC.ContainsItem($"LoadPort.{_module}.EnableAutoCarrierIdRead") ? SC.GetValue($"LoadPort.{_module}.EnableAutoCarrierIdRead") : true; } } public virtual bool IsBypassCarrierIDReader { get { return SC.ContainsItem($"LoadPort.{_module}.BypassCarrierIDReader") ? SC.GetValue($"LoadPort.{_module}.BypassCarrierIDReader") : false; } } private void RegisterOperation() { OP.Subscribe($"{Name}.LoadportHome", (string cmd, object[] param) => { if (!Home(out string reason)) { EV.PostWarningLog(Module, $"{Name} can not start home, {reason}"); return false; } EV.PostInfoLog(Module, $"{Name} start home"); return true; }); OP.Subscribe($"{Name}.LoadportReset", (string cmd, object[] param) => { if (!ClearError(out string reason)) { EV.PostWarningLog(Module, $"{Name} can not reset, {reason}"); return false; } EV.PostInfoLog(Module, $"{Name} start reset"); return true; }); OP.Subscribe($"{Name}.LoadportStop", (string cmd, object[] param) => { if (!Stop(out string reason)) { EV.PostWarningLog(Module, $"{Name} can not stop, {reason}"); return false; } EV.PostInfoLog(Module, $"{Name} stop"); return true; }); OP.Subscribe($"{Name}.LoadportLoad", (string cmd, object[] param) => { if (!Load(out string reason)) { EV.PostWarningLog(Module, $"{Name} can not load, {reason}"); return false; } EV.PostInfoLog(Module, $"{Name} start load"); return true; }); OP.Subscribe($"{Name}.LoadportLoadWithoutMap", (string cmd, object[] param) => { if (!LoadWithoutMap(out string reason)) { EV.PostWarningLog(Module, $"{Name} can not load without map, {reason}"); return false; } EV.PostInfoLog(Module, $"{Name} start load without map"); return true; }); OP.Subscribe($"{Name}.LoadportLoadWithMap", (string cmd, object[] param) => { if (!Load(out string reason)) { EV.PostWarningLog(Module, $"{Name} can not load with map, {reason}"); return false; } if (!QueryWaferMap(out reason)) { EV.PostWarningLog(Module, $"{Name} can not map, {reason}"); return false; } EV.PostInfoLog(Module, $"{Name} start load with map"); return true; }); OP.Subscribe($"{Name}.LoadportUnload", (string cmd, object[] param) => { if (!Unload(out string reason)) { EV.PostWarningLog(Module, $"{Name} can not unload, {reason}"); return false; } EV.PostInfoLog(Module, $"{Name} start unload"); return true; }); OP.Subscribe($"{Name}.LoadportClamp", (string cmd, object[] param) => { if (!Clamp(out string reason)) { EV.PostWarningLog(Module, $"{Name} can not clamp, {reason}"); return false; } EV.PostInfoLog(Module, $"{Name} start clamp"); return true; }); OP.Subscribe($"{Name}.LoadportUnclamp", (string cmd, object[] param) => { if (!Unclamp(out string reason)) { EV.PostWarningLog(Module, $"{Name} can not unclamp, {reason}"); return false; } EV.PostInfoLog(Module, $"{Name} start unclamp"); return true; }); OP.Subscribe($"{Name}.LoadportOpenDoor", (string cmd, object[] param) => { if (!OpenDoor(out string reason)) { EV.PostWarningLog(Module, $"{Name} can not open door, {reason}"); return false; } EV.PostInfoLog(Module, $"{Name} start open door"); return true; }); OP.Subscribe($"{Name}.LoadportOpenDoorNoMap", (string cmd, object[] param) => { if (!OpenDoorNoMap(out string reason)) { EV.PostWarningLog(Module, $"{Name} can not open door, {reason}"); return false; } EV.PostInfoLog(Module, $"{Name} start open door"); return true; }); OP.Subscribe($"{Name}.LoadportCloseDoor", (string cmd, object[] param) => { if (!CloseDoor(out string reason)) { EV.PostWarningLog(Module, $"{Name} can not close door, {reason}"); return false; } EV.PostInfoLog(Module, $"{Name} start close door"); return true; }); OP.Subscribe($"{Name}.LoadportDock", (string cmd, object[] param) => { if (!Dock(out string reason)) { EV.PostWarningLog(Module, $"{Name} can not dock, {reason}"); return false; } EV.PostInfoLog(Module, $"{Name} start dock"); return true; }); OP.Subscribe($"{Name}.LoadportUndock", (string cmd, object[] param) => { if (!Undock(out string reason)) { EV.PostWarningLog(Module, $"{Name} can not undock, {reason}"); return false; } EV.PostInfoLog(Module, $"{Name} start undock"); return true; }); OP.Subscribe($"{Name}.LoadportQueryState", (string cmd, object[] param) => { if (!QueryState(out string reason)) { EV.PostWarningLog(Module, $"{Name} can not query state, {reason}"); return false; } EV.PostInfoLog(Module, $"{Name} start query state"); return true; }); OP.Subscribe($"{Name}.LoadportQueryLED", (string cmd, object[] param) => { if (!QueryIndicator(out string reason)) { EV.PostWarningLog(Module, $"{Name} can not query led state, {reason}"); return false; } EV.PostInfoLog(Module, $"{Name} start query led state"); return true; }); OP.Subscribe($"{Name}.LoadportSetLED", (string cmd, object[] param) => { int light = (int)param[0]; int state = (int)param[1]; if (!SetIndicator((Indicator)light, (IndicatorState)state, out string reason)) { EV.PostWarningLog(Module, $"{Name} can not set led state, {reason}"); return true; } EV.PostInfoLog(Module, $"{Name} start set led state"); return true; }); OP.Subscribe($"{Name}.LoadportMap", (string cmd, object[] param) => { if (!QueryWaferMap(out string reason)) { EV.PostWarningLog(Module, $"{Name} can not map, {reason}"); return false; } EV.PostInfoLog(Module, $"{Name} start map"); return true; }); OP.Subscribe($"{Name}.SetCassetteType", (string cmd, object[] param) => { if (!SetCassetteType(param, out string reason)) { EV.PostWarningLog(Module, $"{Name} can not set type, {reason}"); return false; } EV.PostInfoLog(Module, $"{Name} cassette type have set to {CasstleType}"); return true; }); OP.Subscribe($"{Name}.LoadportForceHome", (string cmd, object[] param) => { if (!ForceHome(out string reason)) { EV.PostWarningLog(Module, $"{Name} can not start force home, {reason}"); return false; } EV.PostInfoLog(Module, $"{Name} start force home"); return true; }); OP.Subscribe($"{Name}.LoadportFOSBMode", (string cmd, object[] param) => { if (!FOSBMode(out string reason)) { EV.PostWarningLog(Module, $"{Name} can not change to FOSB mode, {reason}"); return false; } IsFOSBMode = true; EV.PostInfoLog(Module, $"{Name} changed to FOSB mode"); return true; }); OP.Subscribe($"{Name}.LoadportFOUPMode", (string cmd, object[] param) => { if (!FOUPMode(out string reason)) { EV.PostWarningLog(Module, $"{Name} can not change to FOSB mode, {reason}"); return false; } IsFOSBMode = true; EV.PostInfoLog(Module, $"{Name} changed to FOSB mode"); return true; }); OP.Subscribe($"{Name}.LoadportQueryFOSBMode", (string cmd, object[] param) => { if (!QueryFOSBMode(out string reason)) { EV.PostWarningLog(Module, $"{Name} can not change to FOUP mode, {reason}"); return false; } IsFOSBMode = false; EV.PostInfoLog(Module, $"{Name} changed to FOSB mode"); return true; }); OP.Subscribe($"{Name}.SetLoadportLotID", (string cmd, object[] param) => { if (!SetLotID(param, out string reason)) { return false; } EV.PostInfoLog(Module, $"{Name} set lotID for loadport."); return true; }); } private bool SetLotID(object[] param, out string reason) { reason = ""; if (param == null || param.Length == 0) return false; _lplotID = param[0].ToString(); return true; } private bool SetCassetteType(object[] param, out string reason) { reason = ""; if (param.Length != 1) { reason = "Invalid setting parameter."; return false; } CasstleType = (CasstleType)int.Parse(param[0].ToString()); return true; } public virtual bool FALoad(out string reason) { reason = ""; return true; } public virtual bool Load(out string reason) { reason = ""; return true; } public virtual bool LoadWithoutMap(out string reason) { reason = ""; return true; } public virtual bool QueryWaferMap(out string reason) { reason = ""; return true; } public virtual bool SetWaferMap(out string reason) { reason = ""; return true; } public virtual bool QueryFOSBMode(out string reason) { reason = ""; return true; } /// /// FOSB模式下的Dock指令 /// /// /// public virtual bool FOSBDock(out string reason) { reason = ""; return true; } /// /// FOSB模式下的FOSBUnDock指令 /// /// /// public virtual bool FOSBUnDock(out string reason) { reason = ""; return true; } /// /// FOSB模式下的开门指令 /// /// /// public virtual bool FOSBDoorOpen(out string reason) { reason = ""; return true; } /// /// FOSB模式下的关门指令 /// /// /// public virtual bool FOSBDoorClose(out string reason) { reason = ""; return true; } /// /// FOSB模式下的门下移指令 /// /// /// public virtual bool FOSBDoorDown(out string reason) { reason = ""; return true; } /// /// FOSB模式下的门上移指令 /// /// /// public virtual bool FOSBDoorUp(out string reason) { reason = ""; return true; } public virtual bool SetIndicator(IndicatorType light, IndicatorState state) { if (LoadPortIndicatorLightMap.ContainsKey(light)) { SetIndicator(LoadPortIndicatorLightMap[light], state, out string _); return true; } EV.PostWarningLog(Module, $"Not supported indicator {light}"); return false; } public IndicatorState GetIndicator(IndicatorType light) { if (LoadPortIndicatorLightMap.ContainsKey(light)) { return IndicatorStateFeedback[(int)LoadPortIndicatorLightMap[light]]; } EV.PostWarningLog(Module, $"Not supported indicator {light}"); return IndicatorState.OFF; } public virtual bool SetE84Available(out string reason) { if (_lpE84Callback != null) { _lpE84Callback.SetHoAutoControl(false); _lpE84Callback.SetHoAvailable(true); } reason = ""; return true; } public virtual bool SetE84Unavailable(out string reason) { if (_lpE84Callback != null) { _lpE84Callback.SetHoAutoControl(false); _lpE84Callback.SetHoAvailable(false); } reason = ""; return true; } public virtual bool SetIndicator(Indicator light, IndicatorState state, out string reason) { reason = ""; return true; } public virtual bool QueryIndicator(out string reason) { reason = ""; return true; } public virtual bool QueryState(out string reason) { reason = ""; return true; } public virtual bool Undock(out string reason) { reason = ""; return true; } public virtual bool Dock(out string reason) { reason = ""; return true; } public virtual bool CloseDoor(out string reason) { reason = ""; return true; } public virtual bool OpenDoor(out string reason) { reason = ""; return true; } public virtual bool OpenDoorNoMap(out string reason) { reason = ""; return true; } public virtual bool OpenDoorAndMap(out string reason) { reason = ""; return true; } public virtual bool Unclamp(out string reason) { reason = ""; return true; } public virtual bool Clamp(out string reason) { reason = ""; return true; } public virtual bool Unload(out string reason) { reason = ""; return true; } public virtual bool Stop(out string reason) { reason = ""; return true; } public virtual bool ClearError(out string reason) { reason = ""; return true; } public virtual bool Init(out string reason) { reason = ""; return true; } public virtual bool Home(out string reason) { reason = ""; return true; } public virtual bool ForceHome(out string reason) { reason = ""; return true; } public virtual bool FOSBMode(out string reason) { reason = ""; return true; } public virtual bool FOUPMode(out string reason) { reason = ""; return true; } public virtual bool ReadRfId(out string reason) { reason = ""; return true; } public virtual bool ReadRfid(int startpage, int length, out string reason) { reason = ""; return true; } public virtual bool WriteRfid(string cid, int startpage, int length, out string reason) { reason = ""; return true; } public virtual bool ChangeAccessMode(bool auto, out string reason) { reason = ""; return true; } //public virtual bool ChangeTransferState(LoadPortTransferState newState, out string reason) //{ // reason = ""; // return true; //} public virtual bool SetServiceCommand(bool inService, out string reason) { reason = ""; return true; } public virtual bool GetE84HandoffActiveSignalState(E84PioPosition piopostion, E84PioSignalAtoP AtoPsignal) { if (_lpE84Callback == null) return false; switch (AtoPsignal) { case E84PioSignalAtoP.AM_AVBL: return _lpE84Callback.GetE84SignalState(E84SignalID.AM_AVBL); case E84PioSignalAtoP.BUSY: return _lpE84Callback.GetE84SignalState(E84SignalID.BUSY); case E84PioSignalAtoP.COMPT: return _lpE84Callback.GetE84SignalState(E84SignalID.COMPT); case E84PioSignalAtoP.CONT: return _lpE84Callback.GetE84SignalState(E84SignalID.CONT); case E84PioSignalAtoP.CS_0: return _lpE84Callback.GetE84SignalState(E84SignalID.CS_0); case E84PioSignalAtoP.CS_1: return _lpE84Callback.GetE84SignalState(E84SignalID.CS_1); case E84PioSignalAtoP.TR_REQ: return _lpE84Callback.GetE84SignalState(E84SignalID.TR_REQ); case E84PioSignalAtoP.VALID: return _lpE84Callback.GetE84SignalState(E84SignalID.VALID); default: return false; } } public virtual bool GetE84HandoffPassiveSignalState(E84PioPosition piopostion, E84PioSignalPtoA PtoAsignal) { if (_lpE84Callback == null) return false; switch (PtoAsignal) { case E84PioSignalPtoA.ES: return _lpE84Callback.GetE84SignalState(E84SignalID.ES); case E84PioSignalPtoA.HO_AVBL: return _lpE84Callback.GetE84SignalState(E84SignalID.HO_AVBL); case E84PioSignalPtoA.L_REQ: return _lpE84Callback.GetE84SignalState(E84SignalID.L_REQ); case E84PioSignalPtoA.READY: return _lpE84Callback.GetE84SignalState(E84SignalID.READY); case E84PioSignalPtoA.U_REQ: return _lpE84Callback.GetE84SignalState(E84SignalID.U_REQ); default: return false; } } public virtual void SetE84HandoffSignalState(E84PioPosition piopostion, E84PioSignalPtoA PtoAsignal, bool state) { if (_lpE84Callback == null) return; switch (PtoAsignal) { case E84PioSignalPtoA.ES: _lpE84Callback.SetE84SignalState(E84PassiveSignal.ES, state); break; case E84PioSignalPtoA.HO_AVBL: _lpE84Callback.SetE84SignalState(E84PassiveSignal.HOAvbl, state); break; case E84PioSignalPtoA.L_REQ: _lpE84Callback.SetE84SignalState(E84PassiveSignal.LoadReq, state); break; case E84PioSignalPtoA.READY: _lpE84Callback.SetE84SignalState(E84PassiveSignal.Ready, state); break; case E84PioSignalPtoA.U_REQ: _lpE84Callback.SetE84SignalState(E84PassiveSignal.UnloadReq, state); break; default: break; } } public virtual void Monitor() { _presentTrig.CLK = _isPresent; _placetTrig.CLK = _isPlaced; _dockTrig.CLK = _isDocked; _clampTrig.CLK = ClampState == FoupClampState.Close; _doorTrig.CLK = DoorState == FoupDoorState.Close; _accessSwPressedTrig.CLK = _isAccessSwPressed; if (_lpE84Callback != null) { _lpE84Callback.SetFoupStatus(_isPlaced); _lpE84Callback.SetReadyTransferStatus((ClampState == FoupClampState.Open) && (DockState == FoupDockState.Undocked) && Initalized); } } public virtual void Reset() { Error = false; ExecuteError = false; MapError = false; ReadCarrierIDError = false; if (_carrierIDReadercallback != null) _carrierIDReadercallback.Reset(); } public virtual void Terminate() { } private List> UpdatedWaferIdList() { var wafers = WaferManager.Instance.GetWafers(_module); for (int i = 0; i < wafers.Length; i++) { _waferId[i][1] = wafers[i].LaserMarker; _waferId[i][2] = wafers[i].T7Code; _waferId[i][3] = wafers[i].WaferID; } return _waferId; } public abstract bool IsEnableMapWafer(); public abstract bool IsEnableTransferWafer(); public abstract bool IsEnableTransferWafer(out string reason); public virtual bool IsEnableLoad() { return _isPresent && _isPlaced; } private CarrierOnLPState _CarrierOnState { get; set; } = CarrierOnLPState.Unknow; protected void ConfirmAddCarrier() { if (_isPresent && _isPlaced) { if (_CarrierOnState != CarrierOnLPState.On) { CarrierManager.Instance.CreateCarrier(Name); _CarrierOnState = CarrierOnLPState.On; SerializableDictionary dvid = new SerializableDictionary(); dvid[PORT_ID] = PortId; dvid["PortID"] = PortId; dvid[PORT_CTGRY] = PortCategory; dvid[PORT_CARRIER_TYPE] = InfoPadCarrierType; EV.Notify(EventCarrierArrived, dvid); if (_lpcallback != null) _lpcallback.CarrierArrive(); if (IsAutoClampOnFoupOn) Clamp(out _); if (IsAutoReadCarrierID) ReadRfId(out _); } IsComplete = false; } } protected void ConfirmRemoveCarrier() { if (!_isPlaced) { for (int i = 0; i < _slotNumber; i++) { WaferManager.Instance.DeleteWafer(ModuleHelper.Converter(Name), 0, _slotNumber); } CarrierManager.Instance.DeleteCarrier(Name); if (_CarrierOnState != CarrierOnLPState.Off) { _CarrierOnState = CarrierOnLPState.Off; SerializableDictionary dvid = new SerializableDictionary(); dvid[PORT_ID] = PortId; dvid["PortID"] = PortId; dvid[PORT_CTGRY] = PortCategory; dvid[CAR_ID] = _carrierId ?? ""; dvid["CarrierID"] = _carrierId ?? ""; EV.Notify(EventCarrierRemoved, dvid); if (_lpcallback != null) _lpcallback.CarrerRemove(_carrierId); } IsComplete = false; for (int i = 0; i < _slotNumber; i++) { WaferManager.Instance.DeleteWafer(ModuleHelper.Converter(Name), 0, _slotNumber); } _isMapped = false; _carrierId = ""; } } public void OnSlotMapRead(string _slotMap) { for (int i = 0; i < _slotNumber; i++) { // No wafer: "0", Wafer: "1", Crossed:"2", Undefined: "?", Overlapping wafers: "W" WaferInfoRt wafer = null; switch (_slotMap[i]) { case '0': WaferManager.Instance.DeleteWafer(_module, i); CarrierManager.Instance.UnregisterCarrierWafer(Name, i); break; case '1': wafer = WaferManager.Instance.CreateWafer(_module, i, WaferStatus.Normal); WaferManager.Instance.UpdateWaferSize(_module, i, GetCurrentWaferSize()); CarrierManager.Instance.RegisterCarrierWafer(Name, i, wafer); break; case '2': wafer = WaferManager.Instance.CreateWafer(_module, i, WaferStatus.Crossed); WaferManager.Instance.UpdateWaferSize(_module, i, GetCurrentWaferSize()); CarrierManager.Instance.RegisterCarrierWafer(Name, i, wafer); //NotifyWaferError(Name, i, WaferStatus.Crossed); break; case 'W': wafer = WaferManager.Instance.CreateWafer(_module, i, WaferStatus.Double); WaferManager.Instance.UpdateWaferSize(_module, i, GetCurrentWaferSize()); CarrierManager.Instance.RegisterCarrierWafer(Name, i, wafer); //NotifyWaferError(Name, i, WaferStatus.Double); break; case '?': wafer = WaferManager.Instance.CreateWafer(_module, i, WaferStatus.Unknown); WaferManager.Instance.UpdateWaferSize(_module, i, GetCurrentWaferSize()); CarrierManager.Instance.RegisterCarrierWafer(Name, i, wafer); //NotifyWaferError(Name, i, WaferStatus.Unknown); break; } } SerializableDictionary dvid = new SerializableDictionary(); dvid[SLOT_MAP] = _slotMap; dvid[PORT_ID] = PortId; dvid[PORT_CTGRY] = PortCategory; dvid[CAR_ID] = CarrierId == null ? "" : CarrierId; EV.Notify(EventSlotMapAvailable, dvid); if (_slotMap.Contains("2")) { MapError = true; Error = true; EV.Notify(AlarmLoadPortMappingError, new SerializableDictionary { {"AlarmText","Mapped Crossed wafer." } }); } if (_slotMap.Contains("W")) { MapError = true; Error = true; EV.Notify(AlarmLoadPortMappingError, new SerializableDictionary { {"AlarmText","Mapped Double wafer." } }); } if (_slotMap.Contains("?")) { MapError = true; Error = true; EV.Notify(AlarmLoadPortMappingError, new SerializableDictionary { {"AlarmText","Mapped Unknown wafer." } }); } if (_lpcallback != null) _lpcallback.MappingComplete(_carrierId, _slotMap); _isMapped = true; } private string GetSlotMap() { var wafers = WaferManager.Instance.GetWafers(ModuleHelper.Converter(Name)); string slot = ""; for (int i = 0; i < _slotNumber && i < wafers.Length; i++) { slot += wafers[i].IsWaferEmpty ? "0" : "1"; } return slot; } public bool IsWaferEnableTransfer() { var wafers = WaferManager.Instance.GetWafers(ModuleHelper.Converter(Name)); foreach (var wafer in wafers) { if (wafer.WaferStatus == WaferStatus.Crossed || wafer.WaferStatus == WaferStatus.Double) { EV.PostWarningLog(Name, $"At least one wafer is {wafer.WaferStatus.ToString()}."); return false; } } return true; } /// /// 获取LP中空缺Slot /// /// 返回一个list, 顺序为从下到上.(0-25) public List GetEmptySlot() { List slot = new List(); if (IsMapped) { var wafers = WaferManager.Instance.GetWafers(ModuleHelper.Converter(Name)); for (int i = 0; i < _slotNumber; i++) { if (wafers[i].IsWaferEmpty) slot.Add(i); } return slot; } else { return null; } } public virtual bool ReadCarrierID(int offset = 0, int length = 16) { if (_carrierIDReadercallback != null) return _carrierIDReadercallback.ReadCarrierID(offset, length); return false; } public virtual bool WriteCarrierID(string carrierID, int offset = 0, int length = 16) { if (_carrierIDReadercallback != null) return _carrierIDReadercallback.WriteCarrierID(offset, length, carrierID); return false; } public void OnCarrierIdRead(string carrierId) { if (_isPlaced && _isPresent) { _carrierId = carrierId; SerializableDictionary dvid = new SerializableDictionary(); dvid["CarrierID"] = carrierId ?? ""; dvid[CAR_ID] = carrierId ?? ""; dvid[PORT_ID] = PortId; dvid["PortID"] = PortId; dvid[PORT_CTGRY] = PortCategory; dvid[PORT_CARRIER_TYPE] = InfoPadCarrierType; EV.Notify(EventCarrierIdRead, dvid); CarrierManager.Instance.UpdateCarrierId(Name, carrierId); if (_lpcallback != null) _lpcallback.CarrierIDReadSuccess(_carrierId); ReadCarrierIDError = false; } else { EV.PostWarningLog(Module, $"No FOUP found, carrier id {carrierId} not saved"); } } public void OnCarrierIdRead(ModuleName module, string name, string code) { OnCarrierIdRead(code); } public void ProceedSetCarrierID(string cid) { _carrierId = cid; CarrierManager.Instance.UpdateCarrierId(Name, cid); } public void OnCarrierIdWrite(ModuleName module, string name, string id) { OnCarrierIdWrite(id); } public void OnCarrierIdWrite(string carrierId) { if (_isPlaced && _isPresent) { SerializableDictionary dvid = new SerializableDictionary(); dvid[CAR_ID] = carrierId ?? ""; dvid[PORT_ID] = PortId; dvid[PORT_CTGRY] = PortCategory; EV.Notify(EventCarrierIdWrite, dvid); } else { EV.PostWarningLog(Module, $"No FOUP found, carrier id {carrierId} not saved"); } } public void OnCarrierIdReadFailed(ModuleName module, string name) { OnCarrierIdReadFailed(); } public void OnCarrierIdReadFailed() { if (_isPlaced && _isPresent) { _carrierId = ""; SerializableDictionary dvid = new SerializableDictionary(); dvid[PORT_ID] = PortId; dvid["PortID"] = PortId; dvid[PORT_CTGRY] = PortCategory; EV.Notify(EventCarrierIdReadFailed, dvid); if (_lpcallback != null) _lpcallback.CarrierIDReadFail(); EV.Notify(AlarmCarrierIDReadError, new SerializableDictionary { {"AlarmText","CarrierID read fail." } }); ReadCarrierIDError = true; } else { EV.PostWarningLog(Module, "No FOUP found, carrier id read is not valid"); } } public void OnCarrierIdWriteFailed(ModuleName module, string name) { OnCarrierIdWriteFailed(); } public void OnCarrierIdWriteFailed() { if (_isPlaced && _isPresent) { SerializableDictionary dvid = new SerializableDictionary(); dvid[PORT_ID] = PortId; dvid[PORT_CTGRY] = PortCategory; EV.Notify(EventCarrierIdWriteFailed, dvid); } else { EV.PostWarningLog(Module, "No FOUP found, carrier id not valid"); } } public void OnCarrierIdRead(ModuleName module, string carrierId) { OnCarrierIdRead(carrierId); } public void OnCarrierIdReadFailed(ModuleName module) { OnCarrierIdReadFailed(); } public void OnCarrierIdWrite(ModuleName module, string carrierId) { OnCarrierIdWrite(carrierId); } public void OnCarrierIdWriteFailed(ModuleName module) { OnCarrierIdWriteFailed(); } public void OnRfIdRead(ModuleName module, string rfid) { if (_isPlaced && _isPresent) { _rfid = rfid; SerializableDictionary dvid = new SerializableDictionary(); dvid[CAR_ID] = _carrierId ?? ""; dvid[PORT_ID] = PortId; dvid[PORT_CTGRY] = PortCategory; dvid[RF_ID] = rfid ?? ""; EV.Notify(EventRfIdRead, dvid); CarrierManager.Instance.UpdateRfId(Name, rfid); ReadCarrierIDError = false; } else { EV.PostWarningLog(Module, "No FOUP found, rf id read not valid"); } } public void OnRfIdReadFailed(ModuleName module) { if (_isPlaced && _isPresent) { _rfid = ""; SerializableDictionary dvid = new SerializableDictionary(); dvid[CAR_ID] = _carrierId ?? ""; dvid[PORT_ID] = PortId; dvid[PORT_CTGRY] = PortCategory; EV.Notify(EventRfIdReadFailed, dvid); } else { EV.PostWarningLog(Module, "No FOUP found, rf id read is not valid"); } } public void OnRfIdWrite(ModuleName module, string rfid) { if (_isPlaced && _isPresent) { _rfid = rfid; SerializableDictionary dvid = new SerializableDictionary(); dvid[CAR_ID] = _carrierId ?? ""; dvid[PORT_ID] = PortId; dvid[PORT_CTGRY] = PortCategory; dvid[RF_ID] = rfid ?? ""; EV.Notify(EventRfIdWrite, dvid); CarrierManager.Instance.UpdateRfId(Name, rfid); } else { EV.PostWarningLog(Module, "No FOUP found, rf id write not valid"); } } public void OnRfIdWriteFailed(ModuleName module) { if (_isPlaced && _isPresent) { _rfid = ""; SerializableDictionary dvid = new SerializableDictionary(); dvid[CAR_ID] = _carrierId ?? ""; dvid[PORT_ID] = PortId; dvid[PORT_CTGRY] = PortCategory; dvid[RF_ID] = ""; //EV.PostWarningLog(Module, "Write RFID failed."); EV.Notify(EventRfIdWriteFailed, dvid); } else { EV.PostWarningLog(Module, "No FOUP found, rf id write not valid"); } } public void OnLoaded() { var dvid = new SerializableDictionary { [CAR_ID] = _carrierId ?? "", [PORT_ID] = PortId }; EV.Notify(EventCarrierloaded, dvid); if (_lpcallback != null) _lpcallback.LoadComplete(); //} } public void OnUnloaded() { var dvid = new SerializableDictionary(); dvid[PORT_CTGRY] = PortCategory; dvid[PORT_ID] = PortId; dvid[CAR_ID] = _carrierId ?? ""; EV.Notify(EventCarrierUnloaded, dvid); //} DockState = FoupDockState.Undocked; if (_lpcallback != null) _lpcallback.UnloadComplete(); _isMapped = false; } public void OnE84HandOffStart(bool isload) { if (_lpcallback != null) _lpcallback.OnE84HandoffStart(isload); } public void OnE84HandOffComplete(bool isload) { if (_lpcallback != null) _lpcallback.OnE84HandoffComplete(isload); } public void OnFosbUndock() { var dvid = new SerializableDictionary(); dvid[PORT_CTGRY] = PortCategory; dvid[PORT_ID] = PortId; dvid[CAR_ID] = _carrierId ?? ""; EV.Notify(EventCarrierUnloaded, dvid); //} if (_lpcallback != null) _lpcallback.UnloadComplete(); } public void OnHomed() { //for (int i = 0; i < _slotNumber; i++) //{ WaferManager.Instance.DeleteWafer(ModuleHelper.Converter(Name), 0, _slotNumber); //} _isMapped = false; var dvid = new SerializableDictionary(); dvid[PORT_CTGRY] = PortCategory; dvid[PORT_ID] = PortId; dvid[CAR_ID] = _carrierId ?? ""; EV.Notify(EventLPHomed); if (_lpcallback != null) _lpcallback.OnLPHomed(); } public void OnCloseDoor() { for (int i = 0; i < _slotNumber; i++) { WaferManager.Instance.DeleteWafer(ModuleHelper.Converter(Name), 0, _slotNumber); } _isMapped = false; } public void OnError(string error = "") { EV.Notify($"{_module}{AlarmLoadPortError}", new SerializableDictionary { {"AlarmText",error } }); if (ActionDone != null) ActionDone(false); } protected void SetPresent(bool isPresent) { _isPresent = isPresent; if (_isPresent) { //ConfirmAddCarrier(); } else { //ConfirmRemoveCarrier(); } } protected void SetPlaced(bool isPlaced) { _isPlaced = isPlaced; if (_isPlaced) { ConfirmAddCarrier(); } else { ConfirmRemoveCarrier(); } } public void OnActionDone(bool result) { if (ActionDone != null) ActionDone(result); } } }