Browse Source

1. add the driver of SunWayVPA && the item in config/setmentity
2. add Service Up on TMHome
3. remove the Function of delete the wafer after VCE unload
4. Change Venus's Cycle logic/Job/Sequence the same with Kepler
5. fix some bug in SunWayVce && SunWayRobot

zhouhr 7 months ago
parent
commit
dba64f7240

+ 168 - 0
Venus/Framework/Common/Jobs/SequenceInfo.cs

@@ -311,6 +311,174 @@ namespace MECF.Framework.Common.Jobs
             }
         }
 
+        public static SequenceInfo VenusGetInfo(string seqFile)
+        {
+            SequenceInfo info = new SequenceInfo(seqFile);
+            info.PMs = new List<ModuleName>();
+
+            string content = RecipeFileManager.Instance.GetSequenceAndTryAppendLL(seqFile, false);
+            if (!string.IsNullOrEmpty(content))
+            {
+                try
+                {
+                    XmlDocument dom = new XmlDocument();
+                    dom.LoadXml(content);
+
+                    XmlNodeList lstStepNode = dom.SelectNodes("Aitex/TableSequenceData/Step");
+                    if (lstStepNode == null)
+                    {
+                        //LOG.Error($"{seqFile} has no step");
+                        return null;
+                    }
+
+                    var nodeData = dom.SelectSingleNode("Aitex/TableSequenceData");
+                    if (nodeData != null)
+                    {
+                        var node = nodeData as XmlElement;
+                        info.ThicknessType = node.GetAttribute("ThicknessType");
+                    }
+
+                    foreach (var nodeModelChild in lstStepNode)
+                    {
+                        XmlElement nodeStep = nodeModelChild as XmlElement;
+                        SequenceStepInfo stepInfo = new SequenceStepInfo();
+
+                        foreach (XmlAttribute attr in nodeStep.Attributes)
+                        {
+                            if (attr.Name == "PMARecipe" || attr.Name == "PMBRecipe" || attr.Name == "PMCRecipe" || attr.Name == "PMDRecipe")
+                            {
+                                string module = attr.Name.Substring(0, 3);
+                                var dictionarys = SerializeHelper.Instance.StringToDictionary(attr.Value);
+                                foreach (var dictionary in dictionarys)
+                                {
+                                    string key;
+                                    if (dictionary.Key == "Process")
+                                    {
+                                        key = $"{module}Recipe";
+                                    }
+                                    else
+                                    {
+                                        key = $"{module}{dictionary.Key}";
+                                    }
+                                    stepInfo.StepParameter[key] = dictionary.Value;
+                                }
+                            }
+                            else
+                            {
+                                stepInfo.StepParameter[attr.Name] = attr.Value;
+                            }
+
+                            if (attr.Name == "Position" || attr.Name == "LLSelection" || attr.Name == "PMSelection")
+                            {
+                                if (attr.Value == "LL" || attr.Value == "PM")
+                                    continue;
+
+                                string[] pos = attr.Value.Split(',');
+                                if (pos.Length < 1)
+                                {
+                                    LOG.Write(eEvent.WARN_SEQUENCE, ModuleName.System, $"{seqFile} Position {attr.Value} can not be empty");
+                                    return null;
+                                }
+
+                                foreach (var po in pos)
+                                {
+                                    if (po.IsEmpty())
+                                        continue;
+
+                                    if (attr.Name == "PMSelection")
+                                    {
+                                        info.PMs.Add(ModuleHelper.Converter(po));
+                                    }
+
+                                    if (po == "Cooling")
+                                    {
+                                        stepInfo.StepModules.AddIfNotContains(ModuleName.Cooling1);
+                                        stepInfo.StepModules.AddIfNotContains(ModuleName.Cooling2);
+                                        continue;
+                                    }
+
+                                    if (po == "Aligner")
+                                    {
+                                        stepInfo.StepModules.AddIfNotContains(ModuleName.Aligner1);
+                                        stepInfo.StepModules.AddIfNotContains(ModuleName.Aligner2);
+                                        continue;
+                                    }
+                                    ModuleName module = ModuleHelper.Converter(po);
+                                    if (module == ModuleName.System)
+                                    {
+                                        //LOG.Error($"{seqFile} Position {po} not valid");
+                                        return null;
+                                    }
+
+                                    stepInfo.StepModules.Add(module);
+                                }
+
+                                continue;
+                            }
+
+                            //if (attr.Name == "PMARecipe")
+                            //{
+                            //
+                            //}
+                            //if (attr.Name == "WTWClean")
+                            //{
+                            //    info.WTWCleanRecipe = attr.Value;
+                            //}
+
+                            //if (attr.Name == "PreClean")
+                            //{
+                            //    info.PreWaferCleanRecipe = attr.Value;
+                            //}
+
+                            //if (attr.Name == "PostClean")
+                            //{
+                            //    info.PostWaferCleanRecipe = attr.Value;
+                            //}
+
+                        }
+
+                        info.Steps.Add(stepInfo);
+                    }
+
+                    // Loadlock Single In Single Out property check
+                    var llSteps = info.Steps.FindAll(item => item.StepModules.Contains(ModuleName.LLA) || item.StepModules.Contains(ModuleName.LLB));
+                    if (llSteps.Count == 2)
+                    {
+                        if (llSteps[0].StepModules.Count == 1 && llSteps[1].StepModules.Count == 1)
+                        {
+                            if (llSteps[0].StepModules[0] != llSteps[1].StepModules[0])
+                            {
+                                info.LLInOutPath = llSteps[0].StepModules[0] == ModuleName.LLA ? SequenceLLInOutPath.AInBOut : SequenceLLInOutPath.BInAOut;
+                            }
+                            else
+                            {
+                                info.LLInOutPath = llSteps[0].StepModules[0] == ModuleName.LLA ? SequenceLLInOutPath.AInAOut : SequenceLLInOutPath.BInBOut;
+                            }
+                        }
+
+                        if (llSteps[1].StepParameter.ContainsKey("LLDelayTime"))
+                        {
+                            if (int.TryParse((string)llSteps[1].StepParameter["LLDelayTime"], out int delay))
+                            {
+                                info.LLDelayTime = delay;
+                            }
+                        }
+                    }
+                }
+
+                catch (Exception ex)
+                {
+                    LOG.WriteExeption(ex);
+                    return null;
+                }
+                return info;
+            }
+            else
+            {
+                return null;
+            }
+        }
+
         public static SequenceInfo KeplerGetInfo(string seqFile)
         {
             SequenceInfo info = new SequenceInfo(seqFile);

+ 7 - 0
Venus/Venus_MainPages/Venus_MainPages.csproj

@@ -382,6 +382,9 @@
     <Compile Include="Views\VenusMFCVerificationView.xaml.cs">
       <DependentUpon>VenusMFCVerificationView.xaml</DependentUpon>
     </Compile>
+    <Compile Include="Views\VenusRecipeSequenceSelectView.xaml.cs">
+      <DependentUpon>VenusRecipeSequenceSelectView.xaml</DependentUpon>
+    </Compile>
     <Compile Include="Views\VenusSeOperationOverView.xaml.cs">
       <DependentUpon>VenusSeOperationOverView.xaml</DependentUpon>
     </Compile>
@@ -662,6 +665,10 @@
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>
     </Page>
+    <Page Include="Views\VenusRecipeSequenceSelectView.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
     <Page Include="Views\VenusSeOperationOverView.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>

+ 70 - 44
Venus/Venus_MainPages/ViewModels/SequenceViewModel.cs

@@ -202,7 +202,7 @@ namespace Venus_MainPages.ViewModels
                 {
                     SequenceData sequence = new SequenceData();
                     sequence.Name = fullpath;
-                    sequence.Creator = "Admin";
+                    sequence.Creator = Venus_MainPages.Unity.GlobalUser.Instance.User.Name; ;
                     sequence.CreateTime = DateTime.Now;
                     sequence.Revisor = sequence.Creator;
                     sequence.ReviseTime = DateTime.Now;
@@ -259,7 +259,7 @@ namespace Venus_MainPages.ViewModels
                     }
                     else
                     {
-                        this.CurrentSequence.Revisor = "Admin";
+                        this.CurrentSequence.Revisor = Venus_MainPages.Unity.GlobalUser.Instance.User.Name; ;
                         this.CurrentSequence.ReviseTime = DateTime.Now;
                         if (this.provider.Rename(this.CurrentSequence.Name, fullpath))
                         {
@@ -309,7 +309,7 @@ namespace Venus_MainPages.ViewModels
                     }
                     else
                     {
-                        this.CurrentSequence.Revisor = "Admin";
+                        this.CurrentSequence.Revisor = Venus_MainPages.Unity.GlobalUser.Instance.User.Name; ;
                         this.CurrentSequence.ReviseTime = DateTime.Now;
                         string tempname = this.CurrentSequence.Name;
                         this.CurrentSequence.Name = fullpath;
@@ -469,7 +469,7 @@ namespace Venus_MainPages.ViewModels
         public void SelectRecipe(object select)
         {
             PathFileParam param = (PathFileParam)select;
-            RecipeSequenceSelectView dialog = new RecipeSequenceSelectView()
+            KeplerRecipeSequenceSelectView dialog = new KeplerRecipeSequenceSelectView(param.Value)
             {
                 Owner = Application.Current.MainWindow
             };
@@ -487,35 +487,59 @@ namespace Venus_MainPages.ViewModels
                 }
             }
             List<string> lstFiles = new List<string>();
-            if (param.Name.Contains("Clean"))
-            {
-                lstFiles = provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[1] == "Clean").ToList();//m_uiSequenceManager.GetRecipesByPath($"{param.PrefixPath}");
-            }
-            else
-            {
-                if (param.Name.Contains("PMA"))
-                {
-                    lstFiles = provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[0] == "PMA" && x.Split('\\')[1] == "Process").ToList();
-                }
-                else if (param.Name.Contains("PMB"))
-                {
-                    lstFiles = provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[0] == "PMB" && x.Split('\\')[1] == "Process").ToList();
-                }
-                else if (param.Name.Contains("PMC"))
-                {
-                    lstFiles = provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[0] == "PMC" && x.Split('\\')[1] == "Process").ToList();
-                }
-                else if (param.Name.Contains("PMD"))
-                {
-                    lstFiles = provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[0] == "PMD" && x.Split('\\')[1] == "Process").ToList();
-                }
-                else
-                {
-                    lstFiles = provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[1] == "Process").ToList();
-                }
-            }
 
-            dataContext.Files = new ObservableCollection<FileNode>(RecipeSequenceTreeBuilder.GetFiles("", lstFiles));
+            string moduleName = param.Name.Substring(0, 3);
+
+            var Clean = provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[0] == moduleName && x.Split('\\')[1] == "Clean").ToList();//m_uiSequenceManager.GetRecipesByPath($"{param.PrefixPath}");
+            Clean.Add($"{moduleName}\\Clean\\");
+            var Process = provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[0] == moduleName && x.Split('\\')[1] == "Process").ToList();
+            Process.Add($"{moduleName}\\Process\\");
+            dataContext.Files.AddRange(new ObservableCollection<FileNode>(RecipeSequenceTreeBuilder.GetFiles("", Clean)));
+            dataContext.Files.AddRange(new ObservableCollection<FileNode>(RecipeSequenceTreeBuilder.GetFiles("", Process)));
+            //if (param.Name.Contains("PMA"))
+            //{
+
+
+
+            //}
+            //else if (param.Name.Contains("PMB"))
+            //{
+            //    lstFiles.AddRange(provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[0] == "PMB" && x.Split('\\')[1] == "Clean").ToList());//m_uiSequenceManager.GetRecipesByPath($"{param.PrefixPath}");
+
+            //    lstFiles = provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[0] == "PMB" && x.Split('\\')[1] == "Process").ToList();
+            //}
+            //else if (param.Name.Contains("PMC"))
+            //{
+            //    lstFiles.AddRange(provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[0] == "PMC" && x.Split('\\')[1] == "Clean").ToList());//m_uiSequenceManager.GetRecipesByPath($"{param.PrefixPath}");
+
+            //    lstFiles = provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[0] == "PMC" && x.Split('\\')[1] == "Process").ToList();
+            //}
+            //else if (param.Name.Contains("PMD"))
+            //{
+            //    lstFiles.AddRange(provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[0] == "PMD" && x.Split('\\')[1] == "Clean").ToList());//m_uiSequenceManager.GetRecipesByPath($"{param.PrefixPath}");
+
+            //    lstFiles = provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[0] == "PMD" && x.Split('\\')[1] == "Process").ToList();
+            //}
+            //else
+            //{
+            //    lstFiles.AddRange(provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[1] == "Clean").ToList());//m_uiSequenceManager.GetRecipesByPath($"{param.PrefixPath}");
+
+            //    lstFiles = provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[1] == "Process").ToList();
+            //}
+
+            //if (param.Name.Contains("Clean"))
+            //{
+            //}
+            //else
+            //{
+
+            //}
+
+            //lstFiles.ForEach(x => 
+            //{
+            //    dataContext.Files.Add(new ObservableCollection<FileNode>(RecipeSequenceTreeBuilder.GetFiles("", x)));
+            //});
+            //dataContext.Files = new ObservableCollection<FileNode>(RecipeSequenceTreeBuilder.GetFiles("", lstFiles));
 
             if (dialog.ShowDialog() == true)
             {
@@ -523,17 +547,19 @@ namespace Venus_MainPages.ViewModels
                 //param.Value = $"{param.PrefixPath}\\" + dialog.FullPath;
                 //param.FileName = param.Value;
                 string path = dialog.FullPath;
-                int index = path.LastIndexOf("\\");
-                if (index > -1)
-                {
-                    param.FileName = path.Substring(index + 1);
-                    param.Value = path.Substring(index + 1);
-                }
-                else
-                {
-                    param.FileName = path;
-                    param.Value = path;
-                }
+                //int index = path.LastIndexOf("\\");
+                //if (index > -1)
+                //{
+                //    param.FileName = path.Substring(index + 1);
+                //    param.Value = path.Substring(index + 1);
+                //}
+                //else
+                //{
+                //    param.FileName = path;
+                //    param.Value = path;
+                //}
+                param.FileName = path;
+                param.Value = path;
 
                 param.IsSaved = false;
             }
@@ -585,7 +611,7 @@ namespace Venus_MainPages.ViewModels
                 return false;
             }
 
-            seq.Revisor = "Admin";
+            seq.Revisor = Venus_MainPages.Unity.GlobalUser.Instance.User.Name;
             seq.ReviseTime = DateTime.Now;
             result = this.provider.Save(seq);
 

+ 0 - 2
Venus/Venus_MainPages/ViewModels/VenusDeOperationOverViewModel.cs

@@ -775,8 +775,6 @@ namespace Venus_MainPages.ViewModels
                 {"Module", info.ModuleData.ModuleID},
                 {"SlotSequence", slotSequence.ToArray()},
                 {"AutoStart", true},
-                { "PreCleanRecipeName",info.PreCleanRecipeName},
-                { "PostCleanRecipeName",info.PostCleanRecipeName}
             };
             InvokeClient.Instance.Service.DoOperation("System.CreateSEJob", param);
         }

+ 0 - 2
Venus/Venus_MainPages/ViewModels/VenusSeOperationOverViewModel.cs

@@ -550,8 +550,6 @@ namespace Venus_MainPages.ViewModels
                 {"Module", info.ModuleData.ModuleID},
                 {"SlotSequence", slotSequence.ToArray()},
                 {"AutoStart", true},
-                { "PreCleanRecipeName",info.PreCleanRecipeName},
-                { "PostCleanRecipeName",info.PostCleanRecipeName}
             };
             InvokeClient.Instance.Service.DoOperation("System.CreateSEJob", param);
         }

+ 38 - 13
Venus/Venus_MainPages/Views/SequenceView.xaml

@@ -9,15 +9,17 @@
              prism:ViewModelLocator.AutoWireViewModel="True"
              xmlns:ctrl="http://OpenSEMI.Ctrlib.com/presentation"
              xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
-             
+             xmlns:converters="clr-namespace:Venus_MainPages.Converters"
              xmlns:dgextension="clr-namespace:RecipeEditorLib.DGExtension;assembly=SequenceControl"
              xmlns:sequence="clr-namespace:Venus_MainPages.Sequence"
              d:DesignHeight="450" d:DesignWidth="800" Name="sequenceView">
 
-    <UserControl.Resources>
 
+    <UserControl.Resources>
+        <converters:StringToDictionary x:Key="StringToDictionary"/>
+        <converters:SequenceKeyConverter x:Key="SequenceKeyConverter"/>
         <DataTemplate x:Key="ParamTemplate">
-            <Grid Width="230" Margin="0,5">
+            <Grid Width="270" Margin="0,5">
                 <Grid.LayoutTransform>
                     <TransformGroup>
                         <RotateTransform Angle="-90"/>
@@ -36,7 +38,7 @@
                         <ScaleTransform ScaleX="1" ScaleY="-1" />
                     </TransformGroup>
                 </Grid.LayoutTransform>
-                <Border BorderBrush="{DynamicResource Table_BD}" BorderThickness="0,0,1,1" Padding="5,1" Width="230" Height="30">
+                <Border BorderBrush="{DynamicResource Table_BD}" BorderThickness="0,0,1,1" Padding="5,1" Width="270" Height="30">
                     <TextBlock Visibility="{Binding Visible}" Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" FontSize="14" Width="Auto" />
                 </Border>
             </Grid>
@@ -50,7 +52,7 @@
                         <ScaleTransform ScaleX="1" ScaleY="-1" />
                     </TransformGroup>
                 </Grid.LayoutTransform>
-                <Border BorderBrush="{DynamicResource Table_BD}" BorderThickness="0,1,1,1" Padding="5,1" Width="230" Height="30">
+                <Border BorderBrush="{DynamicResource Table_BD}" BorderThickness="0,1,1,1" Padding="5,1" Width="270" Height="30">
                     <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
                         <ctrl:CheckBoxExt IsChecked="{Binding Checked}" CheckBoxSaved="{Binding IsSaved, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="0,4"/>
                         <TextBlock Visibility="{Binding Visible}" HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" FontSize="14"/>
@@ -67,7 +69,7 @@
                         <ScaleTransform ScaleX="1" ScaleY="-1" />
                     </TransformGroup>
                 </Grid.LayoutTransform>
-                <Border BorderBrush="{DynamicResource Table_BD}" BorderThickness="0,0,1,1" Padding="5,1" Width="230" Height="30">
+                <Border BorderBrush="{DynamicResource Table_BD}" BorderThickness="0,0,1,1" Padding="5,1" Width="270" Height="30">
                     <ctrl:TextBoxEx Visibility="{Binding Visible}" IsEnabled="{Binding IsEnabled}" TextSaved="{Binding IsSaved, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" FontSize="14" Width="Auto" />
                 </Border>
             </Grid>
@@ -81,7 +83,7 @@
                         <ScaleTransform ScaleX="1" ScaleY="-1" />
                     </TransformGroup>
                 </Grid.LayoutTransform>
-                <Border BorderBrush="{DynamicResource Table_BD}" BorderThickness="0,0,1,1" Padding="5,1" Width="230">
+                <Border BorderBrush="{DynamicResource Table_BD}" BorderThickness="0,0,1,1" Padding="5,1" Width="270">
                     <ctrl:TextBoxEx Visibility="{Binding Visible}" EditBoxMode="SignInteger" TextSaved="{Binding IsSaved, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsEnabled="{Binding IsEnabled}" Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" FontSize="14" Width="Auto" />
                 </Border>
             </Grid>
@@ -95,14 +97,36 @@
                         <ScaleTransform ScaleX="1" ScaleY="-1" />
                     </TransformGroup>
                 </Grid.LayoutTransform>
-                <Border BorderBrush="{DynamicResource Table_BD}" BorderThickness="0,0,1,1" Padding="5,1" Width="230" Height="30">
+                <Border BorderBrush="{DynamicResource Table_BD}" BorderThickness="0,0,1,1" Padding="5,1" Width="270" Height="Auto">
                     <Grid >
                         <Grid.ColumnDefinitions>
                             <ColumnDefinition />
                             <ColumnDefinition Width="Auto"/>
                         </Grid.ColumnDefinitions>
-                        <ctrl:TextBoxEx Visibility="{Binding Visible}" IsEnabled="{Binding IsEnabled}" TextSaved="{Binding IsSaved, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" FontSize="12.4" Width="Auto"/>
-                        <Button  Command="{Binding Path=DataContext.SelectRecipeCommand, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}" CommandParameter="{Binding }" Grid.Column="1"  Content="..." Foreground="White" FontSize="20" Visibility="{Binding Visible}" Width="30" Height="20" Margin="5,0,0,0"/>
+                        <!--<Border Visibility="{Binding Visible}" BorderThickness="1" BorderBrush="Black" >
+                            <TextBlock Text="{Binding Value, UpdateSourceTrigger=PropertyChanged}" FontSize="13" Foreground="Black"/>
+                        </Border>-->
+                        <!--<ctrl:TextBoxEx Visibility="{Binding Visible}" IsEnabled="{Binding IsEnabled}" TextSaved="{Binding IsSaved, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  Width="Auto"/>-->
+                        <ListBox ItemsSource="{Binding Value,Converter={StaticResource StringToDictionary}}" Visibility="{Binding Visible}" VerticalAlignment="Center">
+                            <ListBox.ItemTemplate>
+                                <DataTemplate>
+                                    <Grid>
+                                        <Grid.ColumnDefinitions>
+                                            <ColumnDefinition/>
+                                            <ColumnDefinition/>
+                                        </Grid.ColumnDefinitions>
+                                        <Border  BorderThickness="1 .5 0 .5" BorderBrush="gray"  Width="50" Height="25">
+                                            <TextBlock Text="{Binding Key,Converter={StaticResource SequenceKeyConverter}}"  FontSize="13" VerticalAlignment="Center" Padding="1 0 0 0"/>
+                                        </Border>
+                                        <Border Grid.Column="1" BorderThickness="1 .5 1 .5" BorderBrush="Gray"  Width="185" Height="25">
+                                            <TextBlock Text="{Binding Value}" VerticalAlignment="Center"  FontSize="13" Padding="1 0 0 0"/>
+                                        </Border>
+                                    </Grid>
+
+                                </DataTemplate>
+                            </ListBox.ItemTemplate>
+                        </ListBox>
+                        <Button  Command="{Binding Path=DataContext.SelectRecipeCommand, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}" CommandParameter="{Binding }" Grid.Column="1"  Content="..." Foreground="White" FontSize="20" Visibility="{Binding Visible}" Width="20" Height="20"/>
                     </Grid>
                 </Border>
             </Grid>
@@ -116,7 +140,7 @@
                         <ScaleTransform ScaleX="1" ScaleY="-1" />
                     </TransformGroup>
                 </Grid.LayoutTransform>
-                <Border BorderBrush="{DynamicResource Table_BD}" BorderThickness="0,0,1,1" Padding="5,1" Width="230">
+                <Border BorderBrush="{DynamicResource Table_BD}" BorderThickness="0,0,1,1" Padding="5,1" Width="270">
                     <ctrl:ComboBoxExt Style="{StaticResource ResourceKey={x:Type ComboBox}}" 
                                       Visibility="{Binding Visible}" 
                                       ComboBoxSaved="{Binding IsSaved, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
@@ -232,6 +256,7 @@
         </HierarchicalDataTemplate>
         <local:FolderOrFileTemplateSelector x:Key="FolderFileTemplateSelector" FolderTemplate="{StaticResource FolderTemplate}" FileTemplate="{StaticResource FileTemplate}"/>
 
+
         <Style x:Key="SequenceTextBox" TargetType="{x:Type ctrl:TextBoxEx}">
             <Setter Property="SnapsToDevicePixels" Value="True"/>
             <Setter Property="FontFamily" Value="Arial" />
@@ -333,9 +358,9 @@
             </Grid.RowDefinitions>
             <Grid Width="1600" HorizontalAlignment="Left" Margin="10,0,0,0" IsEnabled="{Binding IsPermission}">
                 <Grid.ColumnDefinitions>
-                    <ColumnDefinition Width="230"/>
+                    <ColumnDefinition Width="270"/>
                     <ColumnDefinition Width="10*"/>
-                    <ColumnDefinition Width="230"/>
+                    <ColumnDefinition Width="270"/>
                     <ColumnDefinition Width="8*"/>
                     <ColumnDefinition Width="8*"/>
                     <ColumnDefinition Width="Auto"/>

+ 184 - 0
Venus/Venus_MainPages/Views/VenusRecipeSequenceSelectView.xaml

@@ -0,0 +1,184 @@
+<Window x:Class="Venus_MainPages.Views.VenusRecipeSequenceSelectView"
+                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+    mc:Ignorable="d"
+    WindowStartupLocation="CenterOwner"
+    WindowStyle="SingleBorderWindow" ResizeMode="NoResize" ShowInTaskbar="False"
+    Background="LightSkyBlue" Width="1200" Height="500" Name="recipeSequenceSelect" Loaded="Window_Loaded">
+    <Window.Resources>
+        <HierarchicalDataTemplate x:Key="FileTemplate" ItemsSource="{Binding Files}">
+            <StackPanel>
+                <TextBlock Text="{Binding Name}" />
+            </StackPanel>
+        </HierarchicalDataTemplate>
+    </Window.Resources>
+    <Border BorderBrush="Gray" BorderThickness="0,1,0,0" >
+        <Grid Margin="20,10">
+            <Grid.RowDefinitions>
+                <RowDefinition />
+                <RowDefinition Height="auto"/>
+            </Grid.RowDefinitions>
+            <Grid>
+                <Grid.ColumnDefinitions>
+                    <ColumnDefinition/>
+                    <ColumnDefinition/>
+                    <ColumnDefinition/>
+                    <ColumnDefinition/>
+                    <ColumnDefinition/>
+
+                </Grid.ColumnDefinitions>
+                <GroupBox Header="Pre Lot Clean" FontSize="14" Grid.Column="0">
+                    <Grid>
+                        <Grid.RowDefinitions>
+                            <RowDefinition Height="30"/>
+                            <RowDefinition/>
+                        </Grid.RowDefinitions>
+                        <Border BorderBrush="Black" BorderThickness="1 1 1 0" Background="White">
+                            <StackPanel Orientation="Horizontal">
+                                <TextBlock Text="Recipe:" VerticalAlignment="Center" FontSize="14" Padding="5 0 0 0"/>
+                                <TextBlock x:Name="preLotSelectedRecipeTextBlock" Width="Auto" VerticalAlignment="Center" FontSize="14"/>
+                            </StackPanel>
+                        </Border>
+
+                        <Border Grid.Row="1" BorderBrush="Black" BorderThickness="1" Background="White" MouseDown="PreLotBorder_MouseDown">
+                            <TreeView x:Name="PreLotTreeView"  Margin="5" ItemsSource="{Binding Files[0].Files}" ItemTemplate="{StaticResource FileTemplate}"
+                   VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" SelectedItemChanged="PreClean_PART_TREE_SelectedItemChanged"
+                   Height="{Binding Path=ActualHeight,ElementName=PART_BORDER, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
+                                <!--Height should add for VirtualizingPanel, otherwise the App will be slow-->
+                                <TreeView.ItemContainerStyle>
+                                    <Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource ResourceKey={x:Type TreeViewItem}}">
+                                        <Setter Property="IsExpanded" Value="True"></Setter>
+                                    </Style>
+                                </TreeView.ItemContainerStyle>
+                            </TreeView>
+                        </Border>
+                    </Grid>
+                </GroupBox>
+                <GroupBox Header="Process" FontSize="14" Grid.Column="1">
+                    <Grid>
+                        <Grid.RowDefinitions>
+                            <RowDefinition Height="30"/>
+                            <RowDefinition/>
+                        </Grid.RowDefinitions>
+                        <Border BorderBrush="Black" BorderThickness="1 1 1 0" Background="White">
+                            <StackPanel Orientation="Horizontal">
+                                <TextBlock Text="Recipe:" VerticalAlignment="Center" FontSize="14" Padding="5 0 0 0"/>
+                                <TextBlock x:Name="processSelectedRecipeTextBlock" Width="Auto" VerticalAlignment="Center"  FontSize="14"/>
+                            </StackPanel>
+                        </Border>
+
+                        <Border Grid.Row="1" BorderBrush="Black" BorderThickness="1" Background="White" MouseDown="ProcessBorder_MouseDown">
+                            <TreeView  x:Name="ProcessTreeView" Margin="5" ItemsSource="{Binding Files[1].Files}" ItemTemplate="{StaticResource FileTemplate}"
+                   VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" SelectedItemChanged="Process_PART_TREE_SelectedItemChanged"
+                   Height="{Binding Path=ActualHeight,ElementName=PART_BORDER, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
+                                <!--Height should add for VirtualizingPanel, otherwise the App will be slow-->
+                                <TreeView.ItemContainerStyle>
+                                    <Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource ResourceKey={x:Type TreeViewItem}}">
+                                        <Setter Property="IsExpanded" Value="True"></Setter>
+                                    </Style>
+                                </TreeView.ItemContainerStyle>
+                            </TreeView>
+                        </Border>
+                    </Grid>
+
+                </GroupBox>
+                <GroupBox Header="WTW Clean" FontSize="14" Grid.Column="2" >
+                    <Grid>
+                        <Grid.RowDefinitions>
+                            <RowDefinition Height="30"/>
+                            <RowDefinition/>
+                        </Grid.RowDefinitions>
+                        <Border BorderBrush="Black" BorderThickness="1 1 1 0" Background="White" >
+                            <StackPanel Orientation="Horizontal">
+                                <TextBlock Text="Recipe:" VerticalAlignment="Center" FontSize="14" Padding="5 0 0 0"/>
+                                <TextBlock x:Name="wtwSelectedRecipeTextBlock" Width="Auto" VerticalAlignment="Center"  FontSize="14"/>
+                            </StackPanel>
+                        </Border>
+
+                        <Border  Grid.Row="1" BorderBrush="Black" BorderThickness="1" Background="White" MouseDown="WTWBorder_MouseDown">
+                            <TreeView  x:Name="WTWTreeView" Margin="5" ItemsSource="{Binding Files[0].Files}" ItemTemplate="{StaticResource FileTemplate}"
+                   VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" SelectedItemChanged="WTWClean_PART_TREE_SelectedItemChanged"
+                   Height="{Binding Path=ActualHeight,ElementName=PART_BORDER, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
+                                <!--Height should add for VirtualizingPanel, otherwise the App will be slow-->
+                                <TreeView.ItemContainerStyle>
+                                    <Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource ResourceKey={x:Type TreeViewItem}}">
+                                        <Setter Property="IsExpanded" Value="True"></Setter>
+                                    </Style>
+                                </TreeView.ItemContainerStyle>
+                            </TreeView>
+                        </Border>
+                    </Grid>
+
+                </GroupBox>
+
+                <GroupBox Header="Post Lot Clean" FontSize="14" Grid.Column="3">
+                    <Grid>
+                        <Grid.RowDefinitions>
+                            <RowDefinition Height="30"/>
+                            <RowDefinition/>
+                        </Grid.RowDefinitions>
+                        <Border BorderBrush="Black" BorderThickness="1 1 1 0" Background="White">
+                            <StackPanel Orientation="Horizontal">
+                                <TextBlock Text="Recipe:" VerticalAlignment="Center" FontSize="14" Padding="5 0 0 0"/>
+                                <TextBlock x:Name="postLotSelectedRecipeTextBlock" Width="Auto" VerticalAlignment="Center"  FontSize="14"/>
+                            </StackPanel>
+                        </Border>
+
+                        <Border  Grid.Row="1" BorderBrush="Black" BorderThickness="1" Background="White" MouseDown="PostLotBorder_MouseDown">
+                            <TreeView  x:Name="PostLotTreeView" Margin="5" ItemsSource="{Binding Files[0].Files}" ItemTemplate="{StaticResource FileTemplate}"
+                   VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" SelectedItemChanged="PostClean_PART_TREE_SelectedItemChanged"
+                   Height="{Binding Path=ActualHeight,ElementName=PART_BORDER, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
+                                <!--Height should add for VirtualizingPanel, otherwise the App will be slow-->
+                                <TreeView.ItemContainerStyle>
+                                    <Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource ResourceKey={x:Type TreeViewItem}}">
+                                        <Setter Property="IsExpanded" Value="True"></Setter>
+                                    </Style>
+                                </TreeView.ItemContainerStyle>
+                            </TreeView>
+                        </Border>
+                    </Grid>
+
+                </GroupBox>
+
+                <GroupBox Header="Idle Clean" FontSize="14" Grid.Column="4" >
+                    <Grid>
+                        <Grid.RowDefinitions>
+                            <RowDefinition Height="30"/>
+                            <RowDefinition/>
+                        </Grid.RowDefinitions>
+                        <Border BorderBrush="Black" BorderThickness="1 1 1 0" Background="White" >
+                            <StackPanel Orientation="Horizontal">
+                                <TextBlock Text="Recipe:" VerticalAlignment="Center" FontSize="14" Padding="5 0 0 0"/>
+                                <TextBlock x:Name="idleSelectedRecipeTextBlock" Width="Auto" VerticalAlignment="Center"  FontSize="14"/>
+                                <TextBlock Text="| Time:" Width="Auto" VerticalAlignment="Center"  FontSize="14" Margin="45,0,0,0"/>
+                                <TextBox Width="60" Margin="1,4" x:Name="IdleTime"/>
+                                <TextBlock Text="s" Width="Auto" VerticalAlignment="Center"  FontSize="14"/>
+                            </StackPanel>
+                        </Border>
+
+                        <Border  Grid.Row="1" BorderBrush="Black" BorderThickness="1" Background="White" MouseDown="WTWBorder_MouseDown">
+                            <TreeView  x:Name="LongIdleCleanTreeView" Margin="5" ItemsSource="{Binding Files[0].Files}" ItemTemplate="{StaticResource FileTemplate}"
+   VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" SelectedItemChanged="IdleClean_PART_TREE_SelectedItemChanged"
+   Height="{Binding Path=ActualHeight,ElementName=PART_BORDER, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
+                                <!--Height should add for VirtualizingPanel, otherwise the App will be slow-->
+                                <TreeView.ItemContainerStyle>
+                                    <Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource ResourceKey={x:Type TreeViewItem}}">
+                                        <Setter Property="IsExpanded" Value="True"></Setter>
+                                    </Style>
+                                </TreeView.ItemContainerStyle>
+                            </TreeView>
+                        </Border>
+                    </Grid>
+
+                </GroupBox>
+
+            </Grid>
+            <StackPanel Grid.Row="1" Margin="0,10,0,0" Orientation="Horizontal" HorizontalAlignment="Center">
+                <Button Content="OK" Width="90" Height="30" Click="buttonOK_Click" x:Name="buttonOK"/>
+                <Button Content="Cancel" Margin="10,0,0,0" Width="90" Height="30" Click="buttonCancel_Click" x:Name="buttonCancel"/>
+            </StackPanel>
+        </Grid>
+    </Border>
+</Window>

+ 243 - 0
Venus/Venus_MainPages/Views/VenusRecipeSequenceSelectView.xaml.cs

@@ -0,0 +1,243 @@
+using Aitex.Core.Util;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using Venus_MainPages.Sequence;
+using Venus_Unity;
+
+namespace Venus_MainPages.Views
+{
+    /// <summary>
+    /// VenusRecipeSequenceSelectView.xaml 的交互逻辑
+    /// </summary>
+    public partial class VenusRecipeSequenceSelectView : Window
+    {
+        private FileNode pre_currentFileNode;
+        private FileNode process_currentFileNode;
+        private FileNode wtw_currentFileNode;
+        private FileNode post_currentFileNode;
+
+        SerializableDictionary<string, string> recipeDictionary = new SerializableDictionary<string, string>();
+
+        public string FullPath { get; private set; }
+
+        string value;
+        public VenusRecipeSequenceSelectView(string path)
+        {
+            InitializeComponent();
+
+            value = path;
+        }
+
+        private void buttonCancel_Click(object sender, RoutedEventArgs e)
+        {
+            this.DialogResult = false;
+        }
+
+        private void buttonOK_Click(object sender, RoutedEventArgs e)
+        {
+            this.DialogResult = true;
+            if (pre_currentFileNode != null && pre_currentFileNode.Parent.Name == "Clean")
+            {
+                recipeDictionary.Add("PreLotClean", pre_currentFileNode.Name);
+            }
+            else
+            {
+                recipeDictionary.Add("PreLotClean", "");
+            }
+            if (process_currentFileNode != null && process_currentFileNode.Parent.Name == "Process")
+            {
+                recipeDictionary.Add("Process", process_currentFileNode.Name);
+            }
+            else
+            {
+                recipeDictionary.Add("Process", "");
+            }
+            if (wtw_currentFileNode != null && wtw_currentFileNode.Parent.Name == "Clean")
+            {
+                recipeDictionary.Add("WTWClean", wtw_currentFileNode.Name);
+            }
+            else
+            {
+                recipeDictionary.Add("WTWClean", "");
+            }
+            if (post_currentFileNode != null && post_currentFileNode.Parent.Name == "Clean")
+            {
+                recipeDictionary.Add("PostLotClean", post_currentFileNode.Name);
+            }
+            else
+            {
+                recipeDictionary.Add("PostLotClean", "");
+            }
+
+            this.FullPath = SerializeHelper.Instance.DictionaryToString(recipeDictionary);
+        }
+        private void PreClean_PART_TREE_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
+        {
+            pre_currentFileNode = (FileNode)(sender as TreeView).SelectedItem;
+
+            if (pre_currentFileNode.Parent.Name == "Clean")
+            {
+                preLotSelectedRecipeTextBlock.Text = pre_currentFileNode.Name;
+            }
+            else
+            {
+                preLotSelectedRecipeTextBlock.Text = "";
+            }
+
+        }
+        private void Process_PART_TREE_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
+        {
+            process_currentFileNode = (FileNode)(sender as TreeView).SelectedItem;
+            if (process_currentFileNode.Parent.Name == "Process")
+            {
+                processSelectedRecipeTextBlock.Text = process_currentFileNode.Name;
+            }
+            else
+            {
+                processSelectedRecipeTextBlock.Text = "";
+            }
+        }
+        private void WTWClean_PART_TREE_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
+        {
+            wtw_currentFileNode = (FileNode)(sender as TreeView).SelectedItem;
+
+            if (wtw_currentFileNode.Parent.Name == "Clean")
+            {
+                wtwSelectedRecipeTextBlock.Text = wtw_currentFileNode.Name;
+            }
+            else
+            {
+                wtwSelectedRecipeTextBlock.Text = "";
+            }
+        }
+        private void PostClean_PART_TREE_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
+        {
+            post_currentFileNode = (FileNode)(sender as TreeView).SelectedItem;
+            if (post_currentFileNode.Parent.Name == "Clean")
+            {
+                postLotSelectedRecipeTextBlock.Text = post_currentFileNode.Name;
+            }
+            else
+            {
+                postLotSelectedRecipeTextBlock.Text = "";
+            }
+        }
+
+        private void Window_Loaded(object sender, RoutedEventArgs e)
+        {
+
+            var dictionary = SerializeHelper.Instance.StringToDictionary(value);
+
+            if (dictionary.Keys.Contains("PreLotClean"))
+            {
+                preLotSelectedRecipeTextBlock.Text = dictionary["PreLotClean"];
+                foreach (var item in PreLotTreeView.Items)
+                {
+                    var tvi = (TreeViewItem)PreLotTreeView.ItemContainerGenerator.ContainerFromItem(item);
+                    SetSelect(tvi, dictionary["PreLotClean"]);
+                }
+            }
+
+            if (dictionary.Keys.Contains("Process"))
+            {
+                processSelectedRecipeTextBlock.Text = dictionary["Process"];
+
+                foreach (var item in ProcessTreeView.Items)
+                {
+                    var tvi = (TreeViewItem)ProcessTreeView.ItemContainerGenerator.ContainerFromItem(item);
+                    SetSelect(tvi, dictionary["Process"]);
+                }
+            }
+
+            if (dictionary.Keys.Contains("WTWClean"))
+            {
+                wtwSelectedRecipeTextBlock.Text = dictionary["WTWClean"];
+
+                foreach (var item in WTWTreeView.Items)
+                {
+                    var tvi = (TreeViewItem)WTWTreeView.ItemContainerGenerator.ContainerFromItem(item);
+                    SetSelect(tvi, dictionary["WTWClean"]);
+                }
+            }
+
+            if (dictionary.Keys.Contains("PostLotClean"))
+            {
+                postLotSelectedRecipeTextBlock.Text = dictionary["PostLotClean"];
+                foreach (var item in PostLotTreeView.Items)
+                {
+                    var tvi = (TreeViewItem)PostLotTreeView.ItemContainerGenerator.ContainerFromItem(item);
+                    SetSelect(tvi, dictionary["PostLotClean"]);
+                }
+            }
+
+        }
+
+        void SetSelect(TreeViewItem tvi, string value)
+        {
+            if (tvi.Items.Count > 0)
+            {
+                foreach (var item in tvi.Items)
+                {
+                    var tviChild = (TreeViewItem)tvi.ItemContainerGenerator.ContainerFromItem(item);
+                    var model = (FileNode)item;
+                    if (model.Name == value)
+                    {
+                        tviChild.IsSelected = true;
+                        break;
+                    }
+                    else
+                    {
+                        SetSelect(tviChild, value);
+                    }
+                }
+            }
+        }
+
+
+
+        private void PreLotBorder_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
+        {
+            foreach (var item in PreLotTreeView.Items)
+            {
+                var tvi = (TreeViewItem)PreLotTreeView.ItemContainerGenerator.ContainerFromItem(item);
+                SetSelect(tvi, "");
+            }
+        }
+        private void ProcessBorder_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
+        {
+            foreach (var item in ProcessTreeView.Items)
+            {
+                var tvi = (TreeViewItem)ProcessTreeView.ItemContainerGenerator.ContainerFromItem(item);
+                SetSelect(tvi, "");
+            }
+        }
+        private void WTWBorder_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
+        {
+            foreach (var item in WTWTreeView.Items)
+            {
+                var tvi = (TreeViewItem)WTWTreeView.ItemContainerGenerator.ContainerFromItem(item);
+                SetSelect(tvi, "");
+            }
+        }
+        private void PostLotBorder_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
+        {
+            foreach (var item in PostLotTreeView.Items)
+            {
+                var tvi = (TreeViewItem)PostLotTreeView.ItemContainerGenerator.ContainerFromItem(item);
+                SetSelect(tvi, "");
+            }
+        }
+    }
+}

+ 9 - 9
Venus/Venus_MainPages/Views/WaferAssociationUnit.xaml

@@ -9,7 +9,7 @@
              xmlns:customControls="clr-namespace:Venus_Themes.CustomControls;assembly=Venus_Themes"
              
              xmlns:sys="clr-namespace:System;assembly=mscorlib"
-             d:DesignHeight="450" d:DesignWidth="800" x:Name="WaferUnit">
+             d:DesignHeight="420" d:DesignWidth="800" x:Name="WaferUnit">
     <Grid>
         <Grid.ColumnDefinitions>
             <ColumnDefinition/>
@@ -24,8 +24,8 @@
                 <Grid.RowDefinitions>
                     <RowDefinition Height="30"></RowDefinition>
                     <RowDefinition Height="30"></RowDefinition>
-                    <RowDefinition Height="30"></RowDefinition>
-                    <RowDefinition Height="30"></RowDefinition>
+                    <!--<RowDefinition Height="30"></RowDefinition>
+                    <RowDefinition Height="30"></RowDefinition>-->
                     <RowDefinition Height="30"></RowDefinition>
                     <RowDefinition Height="30"></RowDefinition>
                     <RowDefinition Height="Auto"></RowDefinition>
@@ -44,21 +44,21 @@
 
 
                 </StackPanel>
-                <StackPanel Grid.Row="2" Orientation="Horizontal">
+                <!--<StackPanel Grid.Row="2" Orientation="Horizontal">
                     <TextBlock Text="Pre Clean:"  TextWrapping="Wrap" Foreground="{DynamicResource FG_Black}" FontSize="15" FontFamily="Arial" VerticalAlignment="Center" Width="80"></TextBlock>
                     <customControls:CustomComBobox Width="300" x:Name="preComboBox"  DropDownOpened="preComboBox_DropDownOpened"  SelectionChanged="preComboBox_SelectionChanged" Margin="0 2 0 2"/>
                 </StackPanel>
                 <StackPanel Grid.Row="3" Orientation="Horizontal">
                     <TextBlock Text="Post Clean:"  TextWrapping="Wrap" Foreground="{DynamicResource FG_Black}" FontSize="15" FontFamily="Arial" VerticalAlignment="Center" Width="80"></TextBlock>
                     <customControls:CustomComBobox Width="300" x:Name="postComboBox" DropDownOpened="postComboBox_DropDownOpened"  SelectionChanged="postComboBox_SelectionChanged" Margin="0 3 0 3"/>
-                </StackPanel>
+                </StackPanel>-->
 
-                <StackPanel Grid.Row="4" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
+                <StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
                     <Button Content="Select All"    Height="25"    Command="{Binding SelectAllCommand}"   CommandParameter="{Binding ElementName=WaferUnit,Path=WAInfo}" Width="125" Click="SelectAllButton_Click"/>
                     <Button Content="DeSelect All"  Height="25"    Command="{Binding UnSelectAllCommand}" CommandParameter="{Binding ElementName=WaferUnit,Path=WAInfo}" Width="125" Click="UnSelectAllButton_Click" Margin="1 0 0 0"/>
                 </StackPanel>
                 
-                <Grid Grid.Row="5">
+                <Grid Grid.Row="3">
                     <Grid.ColumnDefinitions>
                         <ColumnDefinition Width="1*"/>
                         <ColumnDefinition Width="2*"/>
@@ -72,11 +72,11 @@
 
                    
                 </Grid>
-                <StackPanel Grid.Row="6" Orientation="Horizontal"  HorizontalAlignment="Center" VerticalAlignment="Center" >
+                <StackPanel Grid.Row="4" Orientation="Horizontal"  HorizontalAlignment="Center" VerticalAlignment="Center" >
                     <Button Content="Create Job" Width="120" Height="25"  Command="{Binding CreateJobCommand}" CommandParameter="{Binding ElementName=WaferUnit,Path=WAInfo}"/>
                     <Button Content="Abort Job"  Width="120" Height="25"  Command="{Binding AbortJobCommand}"  CommandParameter="{Binding WAInfo.JobID,RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" Margin="1 0 0 0"/>
                 </StackPanel>
-                <StackPanel Grid.Row="7" Orientation="Horizontal"  VerticalAlignment="Center" HorizontalAlignment="Center">
+                <StackPanel Grid.Row="5" Orientation="Horizontal"  VerticalAlignment="Center" HorizontalAlignment="Center">
                     <Button Content="Start" Width="100" Height="25" Command="{Binding StartCommand}"  CommandParameter="{Binding ElementName=WaferUnit,Path=WAInfo}"/>
                     <Button Content="Stop" Width="100" Height="25" Margin="30,0,0,0" Command="{Binding StopCommand}" CommandParameter="{Binding ElementName=WaferUnit,Path=WAInfo}"/>
                     <Button Content="Abort" Width="100" Height="25" Margin="30,0,0,0" Command="{Binding AbortCommand}" CommandParameter="{Binding ElementName=WaferUnit,Path=WAInfo}"/>

+ 4 - 4
Venus/Venus_MainPages/Views/WaferAssociationUnit.xaml.cs

@@ -77,12 +77,12 @@ namespace Venus_MainPages.Views
                 cleanRecipes.AddRange(CommonFunction.GetFilesNames(System.IO.Path.Combine(QueryDataClient.Instance.Service.GetData("GetRTPath").ToString(), "Recipes", "PMD", "Clean")).ToList());
             }
             cleanRecipes.Add("");
-            preComboBox.ItemsSource = cleanRecipes.Distinct();
+            //preComboBox.ItemsSource = cleanRecipes.Distinct();
         }
 
         private void preComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
         {
-            WAInfo.PreCleanRecipeName= preComboBox.SelectedValue.ToString();
+            //WAInfo.PreCleanRecipeName= preComboBox.SelectedValue.ToString();
         }
         private void postComboBox_DropDownOpened(object sender, EventArgs e)
         {
@@ -105,12 +105,12 @@ namespace Venus_MainPages.Views
                 cleanRecipes.AddRange(CommonFunction.GetFilesNames(System.IO.Path.Combine(QueryDataClient.Instance.Service.GetData("GetRTPath").ToString(), "Recipes", "PMD", "Clean")).ToList());
             }
             cleanRecipes.Add("");
-            postComboBox.ItemsSource = cleanRecipes.Distinct();
+            //postComboBox.ItemsSource = cleanRecipes.Distinct();
         }
 
         private void postComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
         {
-            WAInfo.PostCleanRecipeName = postComboBox.SelectedValue.ToString();
+            //WAInfo.PostCleanRecipeName = postComboBox.SelectedValue.ToString();
 
         }
         private IEnumerable<string> GetFilesNames(string path)

+ 0 - 2
Venus/Venus_RT/Config/DESequenceFormat.xml

@@ -28,8 +28,6 @@
 			<Item Name="PMCRecipe" DisplayName="PMC Recipe" InputType="RecipeSelection" Parameter="PMC"    Min="0" Max="999999"  />
 			<Item Name="PMDRecipe" DisplayName="PMD Recipe" InputType="RecipeSelection" Parameter="PMD"    Min="0" Max="999999"  />
 
-			<Item Name="WTWClean" DisplayName="WTW Clean" InputType="RecipeSelection"   Min="0" Max="999999"  />
-
 
 			<Item Name="AlignAngle" DisplayName="Align Angle" InputType="NumInput"   Min="0" Max="359"  />
 

+ 0 - 2
Venus/Venus_RT/Config/SESequenceFormat.xml

@@ -26,8 +26,6 @@
 			<Item Name="PMBRecipe" DisplayName="PMB Recipe" InputType="RecipeSelection" Parameter="PMB"    Min="0" Max="999999"  />
 			<Item Name="PMCRecipe" DisplayName="PMC Recipe" InputType="RecipeSelection" Parameter="PMC"    Min="0" Max="999999"  />
 
-			<Item Name="WTWClean" DisplayName="WTW Clean" InputType="RecipeSelection"     Min="0" Max="999999"  />
-
 
 			<Item Name="AlignAngle" DisplayName="Align Angle" InputType="NumInput"   Min="0" Max="359"  />
 

+ 2 - 1
Venus/Venus_RT/Config/System_VenusDE.sccfg

@@ -125,7 +125,8 @@
 		<config default="30" name="HomeTimeout" nameView="Home Timeout" description="TM初始化超时" max="300" min="1" paramter="" tag="" unit="s" type="Integer" />
 		<config default="60" name="MotionTimeout" nameView="Motion Timeout" description="motion time out" max="600" min="1" paramter="" tag="" unit="s" type="Integer" />
 		<config default="127.0.0.1:1103" name="IPAddress" nameView="IP Address" description="TM Robot IP、端口设置;default 10.0.0.100:13000" max="" min="" paramter="" tag="" unit="" type="String" />
-		<config default="COM160" name="AlignerPort" nameView="Aligner APort" description="TM Aligner COM口号" max="" min="" paramter="" tag="" unit="" type="String" />
+		<config default="0" name="AlignerType" nameView="Aligner Type" description="Aligner厂商 0:泓浒 1:素珀" max="" min="" paramter="" tag="" unit="" type="Integer" />
+		<config default="COM160" name="AlignerPort" nameView="Aligner Port" description="TM Aligner COM口号" max="" min="" paramter="" tag="" unit="" type="String" />
 		<config default="2" name="PMAStationNumber" nameView="PMA Station Number" description="PMA Station Number" max="99" min="0" paramter="" tag="" unit="" type="Integer" />
 		<config default="3" name="PMBStationNumber" nameView="PMB Station Number" description="PMB Station Number" max="99" min="0" paramter="" tag="" unit="" type="Integer" />
 		<config default="4" name="PMCStationNumber" nameView="PMC Station Number" description="PMC Station Number" max="99" min="0" paramter="" tag="" unit="" type="Integer" />

+ 9 - 2
Venus/Venus_RT/Devices/PreAligner/HongHuVPA.cs

@@ -37,7 +37,8 @@ namespace Venus_RT.Devices.PreAligner
             AlignWithAngle,
             Reset,
             Scan,
-            RsLT
+            RsLT,
+            ServeUp,
         }
         private Dictionary<int, string> _ErrorCode2Msg = new Dictionary<int, string>()
         {
@@ -51,7 +52,7 @@ namespace Venus_RT.Devices.PreAligner
             { AlignerAction.Home          , "HOME" },//Home 初始化时 error时用
             { AlignerAction.Reset         , "RSET" },//重置 error时用
             { AlignerAction.Scan          , "SCAN" },//扫描整个Wafer参数
-            { AlignerAction.RsLT          , "RSLT" }
+            { AlignerAction.RsLT          , "RSLT" },
             //Read
             //{ "" , "RQCD" },
             //{ "" , "RQCCDPOS" },
@@ -258,6 +259,12 @@ namespace Venus_RT.Devices.PreAligner
             return SendMessage(_Command2Msg[AlignerAction.RsLT]);
         }
 
+        public bool ServeUp()
+        {
+            _state = RState.End;
+            return true;
+        }
+
         public bool CanSendCommand()
         {
             if (Status == RState.Init)

+ 1 - 0
Venus/Venus_RT/Devices/PreAligner/IPreAlign.cs

@@ -23,6 +23,7 @@ namespace Venus_RT.Devices.PreAligner
         bool ReSet();
         bool SCAN();
         bool QueryOffset();
+        bool ServeUp();
 
         bool CanSendCommand();
     }

+ 289 - 0
Venus/Venus_RT/Devices/PreAligner/SunWayVPA.cs

@@ -0,0 +1,289 @@
+using Aitex.Core.RT.Log;
+using Aitex.Core.RT.SCCore;
+using Aitex.Core.Util;
+using MECF.Framework.Common.Communications;
+using MECF.Framework.Common.Equipment;
+using MECF.Framework.Common.SubstrateTrackings;
+using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robot;
+using System;
+using System.Collections.Generic;
+using System.IO.Ports;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using Venus_Core;
+
+namespace Venus_RT.Devices.PreAligner
+{
+    public class SunWayVPA : IPreAlign
+    {
+        private AsyncSerialPort _serialport;//串口
+        private string _newLine = "\r\n";//结束符号
+        private object _locker = new object();//锁变量
+        private bool _IsAsciiMode = true;
+        private PeriodicJob _thread;
+        private RState _state;
+        private Regex _catchErrorCode = new Regex(@"(?<=_ERR )(.*)");
+        private Regex _checkData = new Regex(@"(?<=DATA)(.*)");
+        private LinkedList<string> _lstMessage = new LinkedList<string>();
+        private ModuleName _module;
+
+        private enum AlignerAction
+        {
+            Home,
+            Align,
+            AlignWithAngle,
+            Reset,
+            Scan,
+            RsLT,
+            ServeUp
+        }
+        private Dictionary<int, string> _ErrorCode2Msg = new Dictionary<int, string>()
+        {
+            { 16 , "" },
+        };
+        private Dictionary<AlignerAction, string> _Command2Msg = new Dictionary<AlignerAction, string>()
+        {
+            //Action
+            { AlignerAction.Align         , "ALIGNER ALGN" },//旋转到预设的站点方向
+            { AlignerAction.AlignWithAngle, "MOVT REL" },//旋转到指定的角度
+            { AlignerAction.Home          , "ALIGNER HOME" },//Home 初始化时 error时用
+            { AlignerAction.Reset         , "RSET" },//重置 error时用
+            { AlignerAction.Scan          , "ALIGNER SCAN" },//扫描整个Wafer参数
+            { AlignerAction.RsLT          , "ALIGNER RSLT" },
+            { AlignerAction.ServeUp       , "SET SERVOS ON"}
+            //Read
+            //{ "" , "RQCD" },
+            //{ "" , "RQCCDPOS" },
+            //{ "" , "RQID" },
+            //{ "" , "RQPS" },
+            //Set
+            //{ "" , "" },
+            //Welding
+            //{ "" , "SVCD" },
+        };
+        public ModuleName Module => _module;
+        public bool IsConnect => _serialport.IsConnected;
+        public RState Status => _state;//状态
+
+        public bool IsError => _state == RState.Failed || _state == RState.Timeout;
+
+        private int _ROffset = 0;
+        private int _TOffset = 0;
+        private bool _IsOverRange = false;
+        public int ROffset => _ROffset;
+
+        public int TOffset => _TOffset;
+
+        public bool IsOverRange => _IsOverRange;
+
+        public SunWayVPA(ModuleName module)
+        {
+            _module = module;
+            string port = SC.GetStringValue($"{module}.AlignerPort");
+            _serialport = new AsyncSerialPort(port, 9600, 8, Parity.None, StopBits.One, _newLine, _IsAsciiMode);
+            _serialport.Open();
+            WaferManager.Instance.SubscribeLocation(ModuleName.Aligner1, 1);
+            _serialport.OnDataChanged += OnReceiveData;
+            _state = RState.Init;
+            _thread = new PeriodicJob(50, OnTimer, "OnTimer->Aligner1");
+            _thread.Start();
+        }
+
+        private void OnReceiveData(string obj)
+        {
+            lock (_locker)
+            {
+                if (string.IsNullOrEmpty(_newLine))//没有CR
+                {
+                    _lstMessage.AddLast(obj);//将消息添加到最后
+                    return;
+                }
+                string[] array = obj.Split(_newLine.ToCharArray());//按照cr分开通讯数据
+                foreach (string text in array)
+                {
+                    if (!string.IsNullOrEmpty(text))
+                    {
+                        _lstMessage.AddLast(text + _newLine);//存进list中等待处理
+                    }
+                }
+            }
+        }
+
+        //定时器处理新信息为状态
+        private bool OnTimer()
+        {
+            //线程锁
+            lock (_locker)
+            {
+                //采用ascii码模式处理
+                if (_IsAsciiMode)
+                {
+                    //存在尚未处理的信息
+                    while (_lstMessage.Count > 0)
+                    {
+                        //获取头上的数据
+                        string handlemsg = _lstMessage.First.Value;
+                        Handlemessage(handlemsg);
+                        _lstMessage.RemoveFirst();
+                    }
+                }
+                //采用binary模式处理
+                else
+                {
+
+                }
+
+            }
+            return true;
+        }
+
+        private void Handlemessage(string handlemsg)
+        {
+            //需要按类型进行处理 Action需要将其error
+            bool IsAction = true;
+            handlemsg = handlemsg.Trim();
+            if (IsAction)
+            {
+                switch (handlemsg)
+                {
+                    //正确执行
+                    case "_RDY":
+                        _state = RState.End;
+                        break;
+                    //返回
+                    default:
+                        if (_checkData.IsMatch(handlemsg))
+                        {
+                            string[] data = handlemsg.Split(' ');
+                            _ROffset = Convert.ToInt32(data[2]);
+                            _TOffset = Convert.ToInt32(data[3]);
+
+                            if (data[5] == "Y")
+                            {
+                                _IsOverRange = true;
+                                LOG.Write(eEvent.WARN_DEVICE_INFO, Module, $"Wafer offset is over range");
+                            }
+
+                            if (data[5] == "N")
+                            {
+                                _IsOverRange = false;
+                                LOG.Write(eEvent.EV_DEVICE_INFO, Module, $"Wafer offset is in range");
+                            }
+
+                            LOG.Write(eEvent.EV_DEVICE_INFO, Module, $"Ro{_ROffset} To{_TOffset}");
+                        }
+                        else
+                        {
+                            _state = RState.Failed;
+                            //分两种 1、不按格式的未知错误 2、有错误码的
+                            if (_catchErrorCode.IsMatch(handlemsg))
+                            {
+                                int errorcode = Convert.ToInt32(_catchErrorCode.Match(handlemsg).Value);
+                                if (_ErrorCode2Msg.ContainsKey(errorcode))
+                                {
+                                    LOG.Write(eEvent.ERR_DEVICE_INFO, Module, _ErrorCode2Msg[errorcode]);
+                                }
+                                else
+                                {
+                                    LOG.Write(eEvent.ERR_DEVICE_INFO, Module, $"未知错误码{errorcode}");
+                                }
+                            }
+                            else
+                            {
+                                LOG.Write(eEvent.ERR_DEVICE_INFO, Module, "未收录相关错误");
+                            }
+                        }
+                        break;
+                }
+            }
+
+        }
+
+        private bool SendMessage(string msg, params string[] args)
+        {
+            _state = RState.Running;
+            if (args.Length > 0)//含参
+            {
+                foreach (string arg in args)
+                    msg = msg + " " + arg;
+                LOG.WriteSingeLine(eEvent.EV_DEVICE_INFO, _module, $"Send Command to SunWay Aligner: {msg}");
+                return _serialport.Write(msg + _newLine);
+            }
+            else//空参
+            {
+                LOG.WriteSingeLine(eEvent.EV_DEVICE_INFO, _module, $"Send Command to SunWay Aligner: {msg}");
+                return _serialport.Write(msg + _newLine);
+            }
+        }
+
+        public bool Align()
+        {
+            if (!CanSendCommand())
+                return false;
+            return SendMessage(_Command2Msg[AlignerAction.Align]);
+        }
+
+        public bool AlignWithAngle(float angle)
+        {
+            if (!CanSendCommand())
+                return false;
+            int ang = (int)Math.Floor(angle);//不能用Convert.toInt32("angle") 其遵守四舍五入 此处需向上取整
+            return SendMessage(_Command2Msg[AlignerAction.AlignWithAngle], ang.ToString());
+        }
+
+        public bool Home()
+        {
+            return SendMessage(_Command2Msg[AlignerAction.Home]);
+        }
+
+        public bool QueryOffset()
+        {
+            if (!CanSendCommand())
+                return false;
+            return SendMessage(_Command2Msg[AlignerAction.RsLT]);
+        }
+
+        public bool ReSet()
+        {
+            if (!IsError)
+                return false;
+            return SendMessage(_Command2Msg[AlignerAction.Reset]);
+        }
+
+        public bool SCAN()
+        {
+            if (!CanSendCommand())
+                return false;
+            return SendMessage(_Command2Msg[AlignerAction.Scan]);
+        }
+
+        public bool ServeUp()
+        {
+            return SendMessage(_Command2Msg[AlignerAction.ServeUp]);
+        }
+
+        public bool CanSendCommand()
+        {
+            if (Status == RState.Init)
+            {
+                LOG.Write(eEvent.ERR_DEVICE_INFO, _module, "Aligner is not homed, please home first.");
+                return false;
+            }
+            else if (Status == RState.Running)
+            {
+                LOG.Write(eEvent.ERR_DEVICE_INFO, _module, "Aligner is busy, please wait a minute");
+                return false;
+            }
+            else if (Status == RState.Failed || Status == RState.Timeout)
+            {
+                LOG.Write(eEvent.ERR_DEVICE_INFO, _module, "Aligner has a error, please check and fix the hardware issue and home it");
+                return false;
+            }
+
+            return true;
+        }
+    }
+}

+ 2 - 1
Venus/Venus_RT/Devices/TM/SunWayRobot.cs

@@ -20,7 +20,7 @@ namespace Venus_RT.Devices.TM
     public class SunWayRobot : ITransferRobot
     {
         private readonly AsyncSocket _socket;
-        private const string EOF = "\r";
+        private const string EOF = "\r\n";
         private RState _status;
         private bool _IsHomed;
         private VRStep _currentStep = VRStep.Idle;
@@ -437,6 +437,7 @@ namespace Venus_RT.Devices.TM
 
                 switch (_currentStep)
                 {
+                    case VRStep.ServeOn:
                     case VRStep.Goto:
                     case VRStep.Halt:
                     case VRStep.Move:

+ 30 - 40
Venus/Venus_RT/Devices/VCE/SunWayVce.cs

@@ -412,48 +412,38 @@ namespace Venus_RT.Devices.VCE
 
         private void ReadMapData(string msg)
         {
-            string waferinfo = "";
+            //string waferinfo = "";
             string[] waferitems = msg.Split(',');
             //智能模式 可以识别叠片
-            for (int i = 3; i < waferitems.Length - 1; ++i)
+            for (int i = 2; i <= waferitems.Length - 1; ++i)
             {
-                //如果包含只需要逐个检查
-                if (waferitems[i].Contains('?'))
+                switch (waferitems[i])
                 {
-                    foreach (char j in waferitems[i])
-                    {
-                        if (waferinfo.Length >= 25)
-                            break;
-                        else
-                            waferinfo += j;
-                    }
-                }
-                else
-                    waferinfo += waferitems[i];
-            }
-
-            for (int i = 0; i < waferinfo.Length; ++i)
-            {
-                int slotnum = i;
-                if (slotnum < 25)
-                {
-                    switch (waferinfo[i])
-                    {
-                        case '0':
-                            WaferManager.Instance.DeleteWafer(_LPMs[0].Module, slotnum);
-                            break;
-                        case 'X':
-                            WaferManager.Instance.CreateWafer(_LPMs[0].Module, slotnum, WaferStatus.Normal);
-                            break;
-                        case 'C':
-                            LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, $"Slot {i + 1}:double or dummy wafer.");
-                            WaferManager.Instance.CreateWafer(_LPMs[0].Module, slotnum, WaferStatus.Double);
-                            break;
-                        case '?':
-                            LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, $"Slot {i + 1}:Crossed wafer.");
-                            WaferManager.Instance.CreateWafer(_LPMs[0].Module, slotnum, WaferStatus.Crossed);
-                            break;
-                    }
+                    case "O":
+                        WaferManager.Instance.DeleteWafer(_LPMs[0].Module, i - 2);
+                        break;
+                    case "X":
+                        WaferManager.Instance.CreateWafer(_LPMs[0].Module, i - 2, WaferStatus.Normal);
+                        break;
+                    case "I":
+                        LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, $"Slot {i - 1}:Thin wafer.");
+                        WaferManager.Instance.CreateWafer(_LPMs[0].Module, i - 2, WaferStatus.Dummy);
+                        break;
+                    case "T":
+                        LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, $"Slot {i - 1}:Thick or Double wafer.");
+                        WaferManager.Instance.CreateWafer(_LPMs[0].Module, i - 2, WaferStatus.Double);
+                        break;
+                    case "C":
+                        LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, $"Slot {i - 1}:Crossed wafer.");
+                        WaferManager.Instance.CreateWafer(_LPMs[0].Module, i - 2, WaferStatus.Double);
+                        break;
+                    case "?":
+                        LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, $"Slot {i - 1}:Unknown error wafer.");
+                        WaferManager.Instance.CreateWafer(_LPMs[0].Module, i - 2, WaferStatus.Double);
+                        break;
+                    default:
+                        LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, $"Slot {i - 1} Receive Error Msg:{waferitems}");
+                        break;
                 }
             }
 
@@ -508,8 +498,8 @@ namespace Venus_RT.Devices.VCE
 
         public override bool ServerUp()
         {
-            if (!CheckVceStatus())
-                return false;
+            //if (!CheckVceStatus())
+            //    return false;
             _currentVceMessage = new VceMessage { Head = VceMessageHead.Set, Command = VceCommand.ServerUp, Param = "ALL,ON" };
             _currentMsg = _currentVceMessage.toSunWayString() + _newline;
             _status = RState.Running;

+ 8 - 2
Venus/Venus_RT/Modules/TM/VenusEntity/SEMFPlaceRoutine.cs

@@ -168,7 +168,7 @@ namespace Venus_RT.Modules.TM.VenusEntity
                 .RunIf(PlaceStep.seDoorOpen,                ModuleHelper.IsLoadPort(_targetModule),      VCEDoorOpen,    CheckVCEDoorOpen)
                 .RunIf(PlaceStep.seCheckStatus,             ModuleHelper.IsLoadPort(_targetModule),      VCECheckStatus, CheckStatusIsOk)
                 .Run(PlaceStep.sePlacing,                   Placing,                WaitPlaceDone,       _placingTimeout)
-                .End(PlaceStep.seNotifyDone,                NullFun,                500);
+                .End(PlaceStep.seNotifyDone,                LetWaferTarget,         50);
 
             return Runner.Status;
         }
@@ -199,6 +199,12 @@ namespace Venus_RT.Modules.TM.VenusEntity
             }
         }
 
+        private bool LetWaferTarget()
+        {
+            WaferManager.Instance.WaferMoved(ModuleName.TMRobot, (int)_hand, _targetModule, _targetSlot);
+            return true;
+        }
+
         private bool WaitPlaceDone()
         {
             if (_robot.Status == RState.Running)
@@ -207,7 +213,7 @@ namespace Venus_RT.Modules.TM.VenusEntity
             }
             else if (_robot.Status == RState.End)
             {
-                WaferManager.Instance.WaferMoved(ModuleName.TMRobot, (int)_hand, _targetModule, _targetSlot);
+                //WaferManager.Instance.WaferMoved(ModuleName.TMRobot, (int)_hand, _targetModule, _targetSlot);
                 return true;
             }
             else

+ 16 - 2
Venus/Venus_RT/Modules/TM/VenusEntity/SETMEntity.cs

@@ -283,6 +283,7 @@ namespace Venus_RT.Modules.TM.VenusEntity
         //private int _controlFlowSetPoint = 90;
         private ModuleName _module;
         private int _TMType = 0;
+        private int _AlignerType = 0;
         #endregion
 
 
@@ -300,6 +301,7 @@ namespace Venus_RT.Modules.TM.VenusEntity
             }
 
             _TMType = SC.GetValue<int>($"TM.TMType");
+            _AlignerType = SC.GetValue<int>($"TM.AlignerType");
             if (ModuleHelper.IsInstalled(ModuleName.TMRobot))
             {
                 switch (_TMType)
@@ -313,8 +315,20 @@ namespace Venus_RT.Modules.TM.VenusEntity
                         break;
                 }
             }
-                
-            _vpa = new HongHuVPA(_module);
+
+            switch (_AlignerType)
+            {
+                case 0:
+                    _vpa = new HongHuVPA(_module);
+                    break;
+                case 1:
+                    _vpa = new SunWayVPA(_module);
+                    break;
+                default:
+                    _vpa = new HongHuVPA(_module);
+                    break;
+            }
+            
             _robotWatch = new Stopwatch();
 
             _homeRoutine = new SEMFHomeRoutine(_tm, _robot, _vpa, module);

+ 1 - 1
Venus/Venus_RT/Modules/VCE/VceEntity.cs

@@ -507,7 +507,7 @@ namespace Venus_RT.Modules.VCE
             if (ret == RState.End)
             {
                 _CassetteArrive = false;
-                WaferManager.Instance.DeleteWafer(_modulename, 0, 25);
+                //WaferManager.Instance.DeleteWafer(_modulename, 0, 25);
             }
 
             return ret == RState.End;

+ 4 - 9
Venus/Venus_RT/Modules/VenusDispatcher.cs

@@ -897,9 +897,6 @@ namespace Venus_RT.Modules
             string lotId = jobId;
             if (param.ContainsKey("LotId"))
                 lotId = (string)param["LotId"];
-
-            string preCleanRecipe = param.ContainsKey("PreCleanRecipeName") ? (string)param["PreCleanRecipeName"] : string.Empty;
-            string postCleanRecipe = param.ContainsKey("PostCleanRecipeName") ? (string)param["PostCleanRecipeName"] : string.Empty;
             if (slotSequence.Length != SC.GetValue<int>("EFEM.LoadPort.SlotNumber"))
             {
                 reason = $"slot sequence parameter not valid, length is {slotSequence.Length}, should be {SC.GetValue<int>("EFEM.LoadPort.SlotNumber")}";
@@ -934,8 +931,6 @@ namespace Venus_RT.Modules
             cj.JetState = EnumJetCtrlJobState.Quequed;
             cj.SequenceNameList = slotSequence;
             cj.CycleNumber = _cycleSetPoint;  // only for temperary debug
-            cj.PreJobClean = preCleanRecipe;
-            cj.PostJobClean = postCleanRecipe;
             _lpCycleSP[ModuleHelper.Converter(module)] = _cycleSetPoint;
 
             Dictionary<string, bool[]> seqSlot = new Dictionary<string, bool[]>();
@@ -1008,7 +1003,7 @@ namespace Venus_RT.Modules
             {
                 ProcessJobInfo pj = new ProcessJobInfo();
                 pj.Name = jobId + "_" + (i + 1);
-                pj.Sequence = SequenceInfoHelper.GetInfo(indexSequence[seqs[i]]);
+                pj.Sequence = SequenceInfoHelper.VenusGetInfo(indexSequence[seqs[i]]);
                 if (pj.Sequence == null)
                 {
                     reason = $"invalid sequence[{indexSequence[seqs[i]]}]";
@@ -2103,7 +2098,7 @@ namespace Venus_RT.Modules
                         {
                             //2024-10-31 15:36:19 修改postjob来源
                             //var postClean = pj.Sequence.GetPostCleanRecipe(pm.Key);
-                            var postClean = FindControlJobByName(pj.ControlJobName)?.PostJobClean;
+                            var postClean = pj.Sequence.GetPostCleanRecipe(pm.Key);
                             if (!string.IsNullOrWhiteSpace(postClean))
                             {
                                 pmTask.InvokePostJobClean(postClean);
@@ -2123,7 +2118,7 @@ namespace Venus_RT.Modules
                     {
                         //2024-10-31 15:36:37 修改prejob来源
                         //var preClean = pj.Sequence.GetPreCleanRecipe(pm.Key);
-                        var preClean = FindControlJobByName(pj.ControlJobName)?.PreJobClean;
+                        var preClean = pj.Sequence.GetPreCleanRecipe(pm.Key);
                         if (!string.IsNullOrWhiteSpace(preClean))
                         {
                             pmTask.InvokePreJobClean(preClean);
@@ -2623,7 +2618,7 @@ namespace Venus_RT.Modules
                                             wafer.InnerId,
                                             wafer.ProcessJob.InnerId,
                                             recipeName,
-                                            wafer.ProcessJob.Sequence.WTWCleanRecipe,
+                                            wafer.ProcessJob.Sequence.GetWTWCleanRecipe(pm),
                                             wafer.ProcessJob.Sequence.LLInOutPath,
                                             wafer.ProcessJob.Sequence.LLDelayTime,
                                             IsSequenceNeedAlign(wafer.ProcessJob.Sequence));  // post clean

+ 1 - 0
Venus/Venus_RT/Venus_RT.csproj

@@ -227,6 +227,7 @@
     <Compile Include="Devices\PlasmaController.cs" />
     <Compile Include="Devices\PreAligner\HongHuVPA.cs" />
     <Compile Include="Devices\PreAligner\IPreAlign.cs" />
+    <Compile Include="Devices\PreAligner\SunWayVPA.cs" />
     <Compile Include="Devices\RevtechMatch.cs" />
     <Compile Include="Devices\SkyPump.cs" />
     <Compile Include="Devices\SMCChiller.cs" />

+ 4 - 1
Venus/Venus_UI/Views/ShellView.xaml.cs

@@ -483,7 +483,10 @@ namespace Venus_UI.Views
         }
         private void UIEvents_InitRaiseChangedEvent(string obj)
         {
-            InvokeClient.Instance.Service.DoOperation($"{obj}.Home");
+            if(obj.Contains("VCE"))
+                InvokeClient.Instance.Service.DoOperation($"{obj}.HOME");
+            else
+                InvokeClient.Instance.Service.DoOperation($"{obj}.Home");
         }
         private void UIEvents_AbortRaiseChangedEvent(string obj)
         {