=head
NAME:
DESCRIPTION:
PARAMETER:
{items => [
{
name=>'job',
label=>'料号名',
type=>'editable_enum',
property=>{
tl_field=>[name=>'text'],
tl_data=>[
{name=>'${JOB}',},
{name=>'TL_genesis_work_jobname',},
{name=>'TL_genesis_org_jobname',},
]
},
must_field=>1,
value=>'${JOB}_chk',
},
{
name=>'send_mail',
label=>'是否发邮件',
type=>'editable_enum',
property=>{
tl_field=>[name=>'text'],
tl_data=>[
{name=>'yes',},
{name=>'no',},
]
},
must_field=>1,
value=>'yes',
},
{
name=>'mail_group',
label=>'Mail Group Name',
type=>'string',
must_field=>1,
value => 'goldarea>2.5sqin',
},
]}
VERSION_HISTORY:
V1.00 2011-06-13 Janson Zhang
1.新版本
V1.01 2011-06-13 John Sun
1.INCAM 中没有ATS菜单下的功能,现在用另外一种方法来代替完成,保证INCAM和Genesis能同时运行。
V1.02 2016-10-26 mast pei
修改deleteLayer中的bug
V1.03 2019-07-25 mast pei
添加自动邮件 系统需求:2264
V1.04 2020-08-11 weiss
确认为多card板子时直接完成脚本 CQ2系统需求:2174
V1.05 2020-05-05 mast pei
添加自动邮件 系统需求:2822
修改触发邮件规则 和条件
V1.06 2020-09-07 John
系统需求:3132
Cancel RF PN
HELP:
功能简介
Create PRE prepare step.
参数配置
● 料号名
设置genesis中料号的名字,${JOB}表示跟TopCAM中的料号名字一样,TL_genesis_work_jobname表示用这个料号属性定义的名字
注意事项
●
=cut
#use strict;
#my ($JOB,$GEN,$GUI,$DB,$JOB_ID,$PAR,$APP);
use utf8;
use Encode;
use_module('ATS::GenMath');
use Data::Dump 'dump';
use_module('Top::MailSender');
my $ATS_GenMath = ATS::GenMath->new();
my ($Job,$Step);
my $Return = 'Done';
my $incam = 'no';
if ($GEN->{GEN_TYPE} =~/incam/i) {
$incam = 'yes';
}
###确定料号名;
if (defined $PAR->{job} and ($PAR->{job} eq 'TL_genesis_org_jobname' or $PAR->{job} eq 'TL_genesis_work_jobname')){
$Job = $DB->get_jobinfo(-jobid=>$JOB_ID,-jobcategory=>'work',-jobinfo=>$PAR->{job});
}
elsif(defined $PAR->{job}){
$Job = $PAR->{job};
$Job =~ s/\$\{JOB\}/$JOB/g;
$Job = lc($Job);
}
if ( ! defined $Job or $Job =~ /^\s*$/) {
$GUI->msgbox(-icon=>'error',-text=>'未定义料号名');
return 'Error';
}
my $PLAN_STATE='SHA';
if ( $DB->{DB_NAME} =~ /ATC/i) {
$PLAN_STATE='CQ';
}
###处理step过滤
$PAR->{step_filter} = $PAR->{step_filter} ? $PAR->{step_filter} : '.*';
try{
if ($PLAN_STATE eq 'CQ' and $GUI->confirm("是否存在多card 需要用array拼好后在pre分析?") eq 'yes' ){
return $Return;
}
###检查Genesis料号是否存在并打开
if (! $GEN->isJobExists(job=>$Job) ){
$GUI->msgbox(-icon=>'error',-text=>"料号 $Job 在Genesis中不存在, 请检查!");
return 'Error';
}
$GEN->openJob(job=>$Job) unless ($GEN->isJobOpen(job=>$Job));
###check and get work Step name
my @steps = $GEN->getStepList(job=>$Job);
if ( @steps == 0 ) {
$GUI->msgbox(-icon=>'error',-text=>'在料号中没有Step存在,你将退出!');
return 0;
}
elsif (@steps != 1){
my @tmp_steps = grep(/$PAR->{step_filter}/,@steps);
if ( @tmp_steps == 1 ) {
$Step = $tmp_steps[0];
}
else {
$Step = $GUI->select_step(-title=>'请选择工作Step',
-steplist=>[@tmp_steps],
-selectmode=>'single');
return 'Cancel' unless ($Step);
}
}
else {
$Step = $steps[0];
}
###Open step and clear layer
$GEN->openStep(job=>$Job,name=>$Step);
$GEN->clearLayers();
$GEN->affectedLayer(mode=>'all',affected=>'no');
$GEN->units(type=>'inch');
my $ans = $GEN->PAUSE("Please check the profile which used as check area!");
unless (defined $ans and $ans eq 'OK' ) {return 'Cancel';}
#my $rf_mark= $GUI ->confirm("是否是RF料号");
my $rf_mark="no";
if ($rf_mark eq 'yes'){
$GUI->msgbox(-icon=>'info',-text=>'请检查软板层上是否有SMD/BGA要算金面积');
return unless ($GEN->PAUSE("Pls checking"));
}
my (@tl_data,@Front,@Back,@Probfr,@Probba,@Goldfr,@Goldba,@Drill);
my %matrix=$GEN->getMatrix(job=>$Job,type=>'hash');
foreach my $layer (sort {$matrix{$a}{row} <=> $matrix{$b}{row}} keys %matrix) {
push(@tl_data,{name=>$layer});
push(@Front,{name=>$layer}) if(defined($matrix{$layer}{tl_name}) and $matrix{$layer}{tl_name} =~ /^(top)$/ );
push(@Back,{name=>$layer}) if(defined($matrix{$layer}{tl_name}) and $matrix{$layer}{tl_name} =~ /^(bottom)$/);
push(@Probfr,{name=>$layer}) if($matrix{$layer}{side} eq 'top' and $matrix{$layer}{layer_type} eq 'solder_mask');
push(@Probba,{name=>$layer}) if($matrix{$layer}{side} eq 'bottom' and $matrix{$layer}{layer_type} eq 'solder_mask');
push(@Goldfr,{name=>$layer}) if($matrix{$layer}{side} eq 'top' and $matrix{$layer}{layer_type} eq 'solder_paste');
push(@Goldba,{name=>$layer}) if($matrix{$layer}{side} eq 'bottom' and $matrix{$layer}{layer_type} eq 'solder_paste');
push(@Drill,{name=>$layer}) if($matrix{$layer}{layer_type} eq 'drill');
}
my $layerinfo = [
{type=>'title',property=>{title=>'1.Carbon layer'}},
{
name=>'Carbon_layer',
label=>'Is Carbon layer',
type=>'enum',
property=>{
tl_field=>[name=>'text'],
tl_value_field => 'name',
tl_data=>[
{name=>'Yes',},
{name=>'No',},
]
},
must_field=>1,
value=>'No',
},
{type=>'title',property=>{title=>'2.array or card'}},
{
name=>'sel',
label=>'Surface calculation is based on',
type=>'radio',
property=>{
tl_columns=>3,
tl_list=>['Array'=>'Array','Card'=>'Card'],
},
must_field=>1,
value=>'',
},
{type=>'title',property=>{title=>'3.Setting'}},
{
name=>'Front',
label=>'Front Layer',
type=>'enum', #editable_enum
property=>{
tl_field=>[name=>'text'],
tl_value_field=>'name',
tl_data=>\@Front,
},
must_field=>1,
value => (($#Front == 0) ? $Front[0]->{name} : ''),
},
#2
{
name=>'Probfr',
label=>'Probfr Layer',
type=>'enum',
property=>{
tl_field=>[name=>'text'],
tl_value_field=>'name',
tl_data=>\@Probfr,
},
#must_field=>1,
value => ($#Probfr == 0) ? $Probfr[0]->{name} : '',
},
#3
{
name=>'Goldfr',
label=>'Front Reference Layer',
type=>'enum',
property=>{
tl_field=>[name=>'text'],
tl_value_field=>'name',
#tl_data=>\@Goldfr,
tl_data=>[{name=>''},@Goldfr],
},
#must_field=>1,
value => ($#Goldfr == 0) ? $Goldfr[0]->{name} : '',
},
#4
{
name=>'Reffr',
label=>'Front Reference As',
type=>'enum',
property=>{
tl_field=>[name=>'text'],
tl_value_field=>'name',
tl_data=>[
{name=>''},
{name=>'GOLD'},
{name=>'OSP'},
],
},
value => '',
},
#5
{
name=>'Back',
label=>'Back Layer',
type=>'enum',
property=>{
tl_field=>[name=>'text'],
tl_value_field=>'name',
tl_data=>\@Back,
},
must_field=>1,
value => ($#Back == 0) ? $Back[0]->{name} : '',
},
#6
{
name=>'Probba',
label=>'Probba Layer',
type=>'enum',
property=>{
tl_field=>[name=>'text'],
tl_value_field=>'name',
tl_data=>\@Probba,
},
#must_field=>1,
value => ($#Probba == 0) ? $Probba[0]->{name} : '',
},
#7
{
name=>'Goldba',
label=>'Back Reference Layer',
type=>'enum',
property=>{
tl_field=>[name=>'text'],
tl_value_field=>'name',
tl_data=>\@Goldba,
tl_data=>[{name=>''},@Goldba],
},
value => ($#Goldba == 0) ? $Goldba[0]->{name} : '',
},
#8
{
name=>'Refba',
label=>'Back Reference As',
type=>'enum',
property=>{
tl_field=>[name=>'text'],
tl_value_field=>'name',
tl_data=>[
{name=>''},
{name=>'GOLD'},
{name=>'OSP'},
],
},
value => '',
},
#9
{
name=>'Drill',
label=>'Main Drill Layer',
type=>'enum',
property=>{
tl_field=>[name=>'text'],
tl_value_field=>'name',
tl_data=>[{name=>'NA'},@Drill],
},
must_field=>1,
value => '',
},
#10
{
name=>'Thickness',
label=>'Board Thickness(mm)',
type=>'number',
units=> 'mm',
must_field=>1,
value =>1.0,
validation=>[
{
condition=>'$Value < 0.1',
msg_type=>'error',
msg=>'Value should > 0.1',
style=>{base=>'red'},
},
{
condition=>'$Value > 3',
msg_type=>'error',
msg=>'Value should < 3',
style=>{base=>'red'},
},
]
},
];
$layerinfo = $GUI->show_form(
-title=>'Please fill the layer name',-defaultsize => [740,660],
-showcheck => 1,-gen => $GEN,
-items=>$layerinfo);
return 'Cancel' unless (%$layerinfo);
my $thick=$layerinfo->{'Thickness'}*1000;
$ans = $GEN->PAUSE('Please contourize surface to save script running time');
unless (defined $ans and $ans eq 'OK' ) {
return 'Cancel';
}
@steps = $GEN->getStepList(job=>$Job);
_deleteLayer(step=>$steps[0],layer=>['qec_goldfr','qec_goldba','qec_ospfr','qec_ospba',
'rel_qec_goldfr+qec_ospfr','rel_qec_goldba+qec_ospba',
'qec_goldfr+++','qec_goldba+++','qec_ospfr+++','qec_ospba+++',
'rel_qec_goldfr+qec_ospfr+++','rel_qec_goldba+qec_ospba+++']);
if ($layerinfo->{Drill} eq 'NA'){
$layerinfo->{Drill} = 'ats_drill' ;
$GEN->matrixAddLayer(job=>$Job,layer=>$layerinfo->{Drill},type=>'drill',context=>'board',polarity=>'positive',) unless ($GEN->isLayerExists(job=>$Job,layer=>$layerinfo->{Drill}));
}
_deleteLayer(step=>$Step,layer=>['ref_layer_c_fr','ref_layer_c_ba']);
foreach my $subStep (@steps){
next if ($subStep =~ /^(.*)(\d{8})\-(\d{6})$/) ;
$GEN->openStep(job=>$Job,name=>$subStep);
$GEN->units(type=>'mm');
$GEN->createLayer(job=>$Job,layer=>'ats_empty') unless ($GEN->isLayerExists(job=>$Job,layer=>'ats_empty'));
if ($incam eq 'no'){
if ($layerinfo->{Goldfr} and $layerinfo->{Reffr}){
CreateGoldLayer($layerinfo->{Front},$layerinfo->{Probfr},$layerinfo->{Goldfr},$layerinfo->{Reffr},$layerinfo->{Drill},'qec_goldfr','qec_ospfr');
}
elsif ($layerinfo->{Front} and $layerinfo->{Probfr}){
$GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>[$layerinfo->{Front},$layerinfo->{Probfr}],clear_before=>'yes');
calc_area('ref_layer_c_fr');
}
if ($layerinfo->{Goldba} and $layerinfo->{Refba}){
CreateGoldLayer($layerinfo->{Back} ,$layerinfo->{Probba},$layerinfo->{Goldba},$layerinfo->{Refba},$layerinfo->{Drill},'qec_goldba','qec_ospba') ;
}
elsif ($layerinfo->{Back} and $layerinfo->{Probba}){
$GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>[$layerinfo->{Back},$layerinfo->{Probba}],clear_before=>'yes');
calc_area('ref_layer_c_ba');
}
}
else{
if ($layerinfo->{Goldfr} and $layerinfo->{Reffr}){
INCAM_CreateGoldLayer($layerinfo->{Front},$layerinfo->{Probfr},$layerinfo->{Goldfr},$layerinfo->{Reffr},$layerinfo->{Drill},'qec_goldfr','qec_ospfr',$subStep) ;
}
elsif ($layerinfo->{Front} and $layerinfo->{Probfr}){
$GEN->units(type=>'inch');
INCAM_CreateMetalLayer(step=>$subStep,outputLayer=>'ref_layer_c_fr',ep=>$layerinfo->{Front},sm=>$layerinfo->{Probfr});
}
if ($layerinfo->{Goldba} and $layerinfo->{Refba}){
INCAM_CreateGoldLayer($layerinfo->{Back} ,$layerinfo->{Probba},$layerinfo->{Goldba},$layerinfo->{Refba},$layerinfo->{Drill},'qec_goldba','qec_ospba',$subStep)
}
elsif ($layerinfo->{Back} and $layerinfo->{Probba}){
$GEN->units(type=>'inch');
INCAM_CreateMetalLayer(step=>$subStep,outputLayer=>'ref_layer_c_ba',ep=>$layerinfo->{Back},sm=>$layerinfo->{Probba});
}
}
$GEN->units(type=>'mm');
$GEN->closeStep();
}
_deleteLayer(step=>$Step,layer=>['qec_goldfr+++','qec_goldba+++','qec_ospfr+++','qec_ospba+++',
'rel_qec_goldfr+qec_ospfr+++','rel_qec_goldba+qec_ospba+++']);
$GEN->openStep(job=>$Job,name=>$Step);
$ans = $GEN->PAUSE('Please Check gold layer features,then continue');
unless (defined $ans and $ans eq 'OK' ) {
return 'Cancel';
}
my $info_step=$layerinfo->{sel};
$GEN->openStep(job=>$Job,name=>$Step);
$GEN->units(type=>'mm');
if ($PLAN_STATE eq 'SHA') {
my %guard_warning;
foreach my $ref_layer_c('ref_layer_c_fr','ref_layer_c_ba'){
my $ll='Front';
my @refs= ('qec_goldfr','qec_ospfr');
if ($ref_layer_c eq 'ref_layer_c_ba'){
@refs= ('qec_goldba','qec_ospba') ;
$ll='Back';
}
if (!$GEN->isLayerExists(job=>$Job,layer=>$ref_layer_c)){
foreach my $ggg (@refs){
if ($GEN->isLayerExists(job=>$Job,layer=>$ggg)){
my @steps11 = $GEN->getSubSteps(job=>$Job,step=>$Step);
if (@steps11) {
foreach my $f (@steps11){
$GEN->openStep(job=>$Job,name=>$f);
$GEN->units(type=>'mm');
$GEN->copyLayer(source_job=>$Job,
source_step=>$Step,
source_layer=>$ggg,
dest_layer=>$ref_layer_c.'_tmp',
mode=>'append', #append
invert=>'yes');#|'yes'
}
$GEN->openStep(job=>$Job,name=>$Step);
$GEN->units(type=>'mm');
$GEN->flattenLayer(source_layer=>$ref_layer_c.'_tmp',target_layer=>$ref_layer_c.'_tmp1');
$GEN->copyLayer(source_job=>$Job,
source_step=>$Step,
source_layer=>$ref_layer_c.'_tmp1',
dest_layer=>$ref_layer_c,
#mode=>'append', #append
invert=>'no');#|'yes'
}
else{
$GEN->copyLayer(source_job=>$Job,
source_step=>$Step,
source_layer=>$ggg,
dest_layer=>$ref_layer_c,
mode=>'append', #append
invert=>'no');#|'yes'
}
}
}
}
if ($GEN->isLayerExists(job=>$Job,layer=>$ref_layer_c)){
my $ff = exposed_pad_size($Job,$Step,$layerinfo->{$ll},$ref_layer_c,$info_step);
foreach my $num (keys %$ff){
$guard_warning{$ll}{$num}=$ff->{$num};
}
}
else{
$guard_warning{1} ="On $ll side, All layer exposed";
}
}
if (keys %guard_warning) {
my $subject = "AUTO MAIL:GE01 risk PN[$JOB]";
my $sent_mail = "Base on [$info_step],High Risk PN [$JOB]:
";
$sent_mail.='Design information:
';
$sent_mail.='1, ID Print Side: ${ID_LAYER}
';
$sent_mail.='2, MF information: ${Array}/Panel, ${PCB}/Array
';
my $n1=3;
foreach my $layer (qw/Front Back/){
if (keys %{$guard_warning{$layer}}){
$sent_mail.='On '.$layer.'
';
for my $n (1,2){
$sent_mail.=$n1.','.$guard_warning{$layer}{$n}.'
';
$n1++;
}
}
}
$sent_mail.='
Action required:
';
$sent_mail.='SM to MF: Use Panel interleaf
';
#$sent_mail.='RT to FI: Use Array interleaf (FR4)
';
$sent_mail.='${et_workflow_sap}
';
$sent_mail.='Part number alarm information:
';
foreach my $layer (qw/Front Back/){
if (@{$guard_warning{$layer}{3}}) {
$sent_mail.='On '.$layer.'
';
foreach my $f (@{$guard_warning{$layer}{3}}){
$sent_mail.=$f;
}
}
}
#$GUI->debug("$sent_mail");
$DB->save_jobinfo(
-jobid=>$JOB_ID,
-jobcategory=>'org',
-jobinfohash=>{ATS_GE01_mail =>$sent_mail});
}
}
my %surface;
$surface{'gold_fr'}=0;
$surface{'gold_ba'}=0;
$surface{'gold_total'}=0;
if($layerinfo->{Probfr}){
$surface{'cp_fr'}=exposedArea($Job,$Step,$thick,$layerinfo->{Front},$layerinfo->{Probfr},'','',$layerinfo->{Drill});
}
else{
$surface{'cp_fr'}=expcopperArea($Job,$Step,$thick,$layerinfo->{Front},$layerinfo->{Probfr},'','',$layerinfo->{Drill});
}
if($layerinfo->{Probba}){
$surface{'cp_ba'}=exposedArea($Job,$Step,$thick,'','',$layerinfo->{Back},$layerinfo->{Probba},$layerinfo->{Drill});
}
else{
$surface{'cp_ba'}=expcopperArea($Job,$Step,$thick,'','',$layerinfo->{Back},$layerinfo->{Probba},$layerinfo->{Drill});
}
$surface{'ref_fr'}=$layerinfo->{Reffr};
$surface{'ref_ba'}=$layerinfo->{Refba};
$surface{'gold_fr'}=exposedArea($Job,$Step,$thick,$layerinfo->{Front},'qec_goldfr',$layerinfo->{Back},'ats_empty',$layerinfo->{Drill}) if ($layerinfo->{Goldfr} and $layerinfo->{Reffr});
$surface{'gold_ba'}=exposedArea($Job,$Step,$thick,$layerinfo->{Front},'ats_empty',$layerinfo->{Back},'qec_goldba',$layerinfo->{Drill}) if ($layerinfo->{Goldba} and $layerinfo->{Refba});
if(($layerinfo->{Goldfr} eq '' or $layerinfo->{Goldfr} == 0) and $layerinfo->{Reffr} =~ /gold/i and !$layerinfo->{Goldfr}){
$surface{'gold_fr'}=$surface{'cp_fr'};
}
if(($layerinfo->{Goldba} eq '' or $layerinfo->{Goldba} == 0) and $layerinfo->{Refba} =~ /gold/i and !$layerinfo->{Goldba}){
$surface{'gold_ba'}=$surface{'cp_ba'};
}
$surface{'cp_total'}=$surface{'cp_fr'}+$surface{'cp_ba'};
$surface{'gold_total'}=$surface{'gold_fr'}+$surface{'gold_ba'} if ($surface{'gold_fr'} and $surface{'gold_ba'});
$surface{'carbon'}='__NA__';
if ( $layerinfo->{Carbon_laye} eq 'Yes'){
$surface{'carbon'}=0;
my @layer = $GUI->select_layer( -title=>'Select Carbon Layers',
-layermatrix=>{$GEN->getMatrix(job=>$Job)},
-default => [],
-selectmode => 'multiple');
return 'Cancel' if(!defined($layer[0]));
foreach my $layer (@layer) {
my $reprot = $GEN->copperArea(layer1=>$layer);
my $tmp = sprintf ('%.4f',$reprot->{area});
$surface{'carbon'}+=$tmp;
}
$surface{'carbon'}=$surface{'carbon'} / 10000;
$surface{'carbon'}=sprintf('%.4f',$surface{'carbon'});
}
$surface{'baseon'} = $info_step;
# $GEN->PAUSE("$surface{baseon} g $surface{ref_fr} h $surface{ref_ba} ");
my %InfoHash;
$InfoHash{TL_exposed_area_front}=$surface{cp_fr};
$InfoHash{TL_exposed_area_back}=$surface{cp_ba};
$InfoHash{TL_gold_area_front}=$surface{gold_fr} * 1.1;
$InfoHash{TL_gold_area_back}=$surface{gold_ba} * 1.1;
#
if ($layerinfo->{Goldfr}) {
$InfoHash{ATS_selection_reference_layer_front}=$layerinfo->{Goldfr};
$InfoHash{ATS_selection_reference_type_front}=$surface{ref_fr};
## Fix BUG 2017-04-25 When REF GOLD, Set REF = GOLD AREA,
## ELSE ,Set REF = ALL - GOLD AREA
if ($InfoHash{ATS_selection_reference_type_front} eq 'GOLD') {
$InfoHash{ATS_selection_reference_area_front}=$surface{gold_fr};
}else {
$InfoHash{ATS_selection_reference_area_front}=$surface{cp_fr} - $surface{gold_fr};
}
$InfoHash{ATS_org_area_type_full_front}='';
}else {
$InfoHash{ATS_selection_reference_layer_front}='';
$InfoHash{ATS_selection_reference_type_front}='';
$InfoHash{ATS_selection_reference_area_front}='';
$InfoHash{ATS_org_area_type_full_front}='GOLD';
}
if ($layerinfo->{Goldba}) {
$InfoHash{ATS_selection_reference_layer_back}=$layerinfo->{Goldba};
$InfoHash{ATS_selection_reference_type_back}=$surface{ref_ba};
if ($InfoHash{ATS_selection_reference_type_back}eq 'GOLD') {
$InfoHash{ATS_selection_reference_area_back}=$surface{gold_ba};
}else {
$InfoHash{ATS_selection_reference_area_back}= $surface{cp_ba} - $surface{gold_ba};
}
$InfoHash{ATS_org_area_type_full_back}='';
}else {
$InfoHash{ATS_selection_reference_layer_back}='';
$InfoHash{ATS_selection_reference_type_back}='';
$InfoHash{ATS_selection_reference_area_back}='';
$InfoHash{ATS_org_area_type_full_back}='GOLD';
}
$InfoHash{ATS_org_area_pe_check}='no';
$InfoHash{TL_carbon_area}=$surface{carbon};
$InfoHash{ATS_surface_area_base_on}=$surface{baseon};
$DB->save_jobinfo(
-jobid=>$JOB_ID,
-jobcategory=>'org',
-jobinfohash=>\%InfoHash);
my $Check_gold_size= sprintf('%-15s',' ').sprintf('%-15s','Exposed').sprintf('%-15s','Gold').sprintf('%-15s','Sel.Ref (sqin)')."\n";
my $Check_gold_state = 0;
my($step_size_x,$step_size_y);
if ($Job =~ /^coc/i ){
my $tmpm1=$InfoHash{TL_gold_area_front}*15.500031000062;
my $tmpm2=$InfoHash{TL_gold_area_back}*15.500031000062;
my $tmpm3=$InfoHash{TL_exposed_area_front}*15.500031000062;
my $tmpm4=$InfoHash{TL_exposed_area_back}*15.500031000062;
$tmpm1=sprintf "%.4f",$tmpm1;
$tmpm2=sprintf "%.4f",$tmpm2;
$tmpm3=sprintf "%.4f",$tmpm3;
$tmpm4=sprintf "%.4f",$tmpm4;
if ($tmpm1 > 2.5 or $tmpm2 > 2.5 and $InfoHash{selection_reference_type_front} =~/^gold$/i and $InfoHash{selection_reference_type_back} =~/^gold$/i){
$Check_gold_state=1;
}
$Check_gold_size.= sprintf('%-15s','front').sprintf('%-15s',$tmpm3).sprintf('%-15s',$tmpm1).sprintf('%-15s',$InfoHash{selection_reference_type_front})."\n";
$Check_gold_size.= sprintf('%-15s','back').sprintf('%-15s',$tmpm4).sprintf('%-15s',$tmpm2).sprintf('%-15s',$InfoHash{selection_reference_type_back})."\n";
my $tmpmm="Base on :$InfoHash{surface_area_base_on}";
$Check_gold_size.= sprintf('%-15s',$tmpmm)."\n";
}
unless ($GEN->{STATUS}){
return $Return;
}
else{
$GUI->msgbox(-icon=>'error',-text=>join("\n",@{$GEN->{STATUS}}));
addFlowNotes(-notes=>" Genesis Error:\n ".join("\n ",@{$GEN->{STATUS}}));
return 'Error';
}
}
catch Error::Simple with {
my $error = encode("utf8",shift);
$GUI->msgbox(-icon=>'error',-text=>$error);
return 'Error';
}
finally{
};
sub _deleteLayer{
my %par = @_;
foreach my $layer(@{$par{layer}}){
$GEN->deleteLayer(layer=>$layer) if ($GEN->isLayerExists(job=>$Job,layer=>$layer));
}
$GEN->openStep(job=>$Job,name=>$par{step}) if ($par{step});
}
sub CreateGoldLayer{
my ($ep,$sm,$ref,$refas,$drill,$gold,$osp) = @_;
$GEN->COM('chklist_single',action=>'ats_dfm_sit',show=>'no');
$GEN->COM('chklist_cupd',chklist=>'ats_dfm_sit',nact=>1,
params=>"((pp_outlayer=$ep)(pp_smlayer=$sm)(pp_refmode=$refas)(pp_reflayer=$ref)(pp_drilllayer=$drill)(pp_goldlayer=$gold)(pp_osplayer=$osp))",
mode=>'regular');
$GEN->COM('chklist_run',chklist=>'ats_dfm_sit',
nact=>1,area=>'global');
`touch /tmp/script.flag` if( ! (-e "/tmp/script.flag"));
}
sub INCAM_CreateGoldLayer{
my ($ep,$sm,$ref,$refas,$drill,$gold,$osp,$subStep) = @_;
my $tmp_sm = 'script_sm';
my $tmp_ep = 'script_ep';
my $tmp_sm_backup = 'ref_expgold+exposp';
$GEN->units(type=>'mm');
_deleteLayer(step=>$subStep,layer=>[$tmp_sm,$tmp_ep,$tmp_sm_backup]);
$GEN->workLayer(name=>$sm,display_number=>1,clear_before=>'yes');
$GEN->selCopyOther(dest=>'layer_name',target_layer=>$tmp_sm);
$GEN->workLayer(name=>$tmp_sm,display_number=>1,clear_before=>'yes');
$GEN->COM("sel_contourize,accuracy=0,break_to_islands=yes,clean_hole_size=0,clean_hole_mode=x_and_y");
$GEN->selCopyOther(dest=>'layer_name',target_layer=>$tmp_sm_backup);
$GEN->workLayer(name=>$ep,display_number=>1,clear_before=>'yes');
$GEN->selCopyOther(dest=>'layer_name',target_layer=>$tmp_ep);
$GEN->workLayer(name=>$tmp_ep,display_number=>1,clear_before=>'yes');
$GEN->COM("sel_contourize,accuracy=0,break_to_islands=yes,clean_hole_size=0,clean_hole_mode=x_and_y");
$GEN->selCopyOther(dest=>'layer_name',target_layer=>$tmp_sm,invert=>'yes',size=>2);
$GEN->workLayer(name=>$tmp_sm,display_number=>1,clear_before=>'yes');
$GEN->COM("sel_contourize,accuracy=0,break_to_islands=yes,clean_hole_size=0,clean_hole_mode=x_and_y");
$GEN->selCopyOther(dest=>'layer_name',target_layer=>$tmp_sm_backup,invert=>'yes',size=>2);
$GEN->workLayer(name=>$tmp_sm_backup,display_number=>1,clear_before=>'yes');
$GEN->COM("sel_contourize,accuracy=0,break_to_islands=yes,clean_hole_size=0,clean_hole_mode=x_and_y");
$GEN->selRefFeat(
layers=>$ref,
use=>'filter',
mode=>'touch',
f_types=>'surface\;pad\;text\;line\;arc',
polarity=>'positive',
);
if ( $GEN->getSelectCount() > 0 ){
if ($refas eq 'GOLD'){
$GEN->selMoveOther(target_layer=>$gold) ;
$GEN->selMoveOther(target_layer=>$osp) ;
}elsif($refas eq 'OSP'){
$GEN->selMoveOther(target_layer=>$osp) ;
$GEN->selMoveOther(target_layer=>$gold) ;
}
}
_deleteLayer(layer=>[$tmp_sm,$tmp_ep,$tmp_sm_backup]);
$GEN->units(type=>'inch');
`touch /tmp/script.flag` if( ! (-e "/tmp/script.flag"));
}
sub expcopperArea {
my ($job,$step,$thick,$layer1,$mask1,$layer2,$mask2,$drill) = @_;
$GEN->openStep(job=>$Job,name=>$Step);
$GEN->units(type=>'mm');
my $reprot;
$reprot =$GEN->copperArea(
'layer1'=>$layer1?$layer1:'',
'layer2'=>$layer2?$layer2:'',
'drills'=>$drill?'yes':'no',
'consider_rout'=>'no',
'drills_source'=>'matrix',
'drills_list'=>$drill,
'thickness'=>$thick,
'resolution_value'=>10,
'x_boxes'=>3,
'y_boxes'=>3,
'area'=>'no',
'dist_map'=>'yes'
);
$reprot = sprintf "%0.4f",$reprot->{area}/10000;
return $reprot;
}
sub exposedArea {
# ($thick,$layerinfo->{Front},'qec_goldfr',$layerinfo->{Back},'ats_empty',$layerinfo->{Drill}) if ($layerinfo->{Goldfr} and $layerinfo->{Reffr});
# ($thick,$layerinfo->{Front},'ats_empty',$layerinfo->{Back},'qec_goldba',$layerinfo->{Drill}) if ($layerinfo->{Goldba} and $layerinfo->{Refba});
my ($job,$step,$thick,$layer1,$mask1,$layer2,$mask2,$drill) = @_;
$GEN->openStep(job=>$Job,name=>$Step);
$GEN->units(type=>'mm');
my $reprot;
$reprot = $GEN->exposedArea(
'layer1'=>$layer1?$layer1:'',
'mask1'=>$mask1?$mask1:'',
'layer2'=>$layer2?$layer2:'',
'mask2'=>$mask2?$mask2:'',
'drills'=>$drill?'yes':'no',
'consider_rout'=>'no',
'drills_source'=>'matrix',
'drills_list'=>$drill,
'thickness'=>$thick,
'resolution_value'=>10,
'x_boxes'=>3,
'y_boxes'=>3,
'area'=>'no',
'dist_map'=>'yes',
);
$reprot = sprintf "%0.4f",$reprot->{area}/10000;
return $reprot;
}
sub exposed_pad_size{
my $Job=shift;
my $Step= shift;
my $layer= shift;
my $ref_layer=shift;
my $base_on =shift;
$GEN->openStep(job=>$Job,name=>$Step);
$GEN->units(type=>'mm');
$GEN->workLayer(name=>$ref_layer,display_number=>1,clear_before=>'yes');
$GEN->COM("sel_contourize,accuracy=0,break_to_islands=yes,clean_hole_size=0,clean_hole_mode=x_and_y");
$GEN->COM("sel_clean_surface,accuracy=10,clean_size=75,clean_mode=x_or_y,max_fold_len=0");
$GEN->COM("sel_clean_surface,accuracy=2.54,clean_size=75,clean_mode=x_and_y,max_fold_len=0");
$GEN->copyLayer(source_job=>$Job,
source_step=>$Step,
source_layer=>$layer,
dest_layer=>'copper_cal',
);
my $copper_a =$GEN->copperArea(
'layer1'=>'copper_cal',
'layer2'=>'',
'drills'=>'no',
'consider_rout'=>'no',
'drills_source'=>'matrix',
'drills_list'=>'',
'thickness'=>'1',
'resolution_value'=>10,
'x_boxes'=>3,
'y_boxes'=>3,
'area'=>'no',
'dist_map'=>'yes'
);
$copper_a = sprintf "%0.4f",$copper_a->{area};
my $f_all =$GEN->copperArea(
'layer1'=>$ref_layer,
'layer2'=>'',
'drills'=>'no',
'consider_rout'=>'no',
'drills_source'=>'matrix',
'drills_list'=>'',
'thickness'=>'1',
'resolution_value'=>10,
'x_boxes'=>3,
'y_boxes'=>3,
'area'=>'no',
'dist_map'=>'yes'
);
$f_all = sprintf "%0.4f",$f_all->{area};
my $percent =12;
my $all_percent = 45;#
my $all_ratio = sprintf "%0.3f",($f_all/$copper_a)*100;
my %guard_warning1=();
my ($condition1,$condition2);
my @guard_warning1;
if ($all_ratio >= $all_percent) {
$condition2 ='ok';
push @guard_warning1,"All exposed pad area: ${f_all} mm2 ; Ratio: $all_ratio%";
}
my @features1 = $GEN->getFeatures(job=>$Job,step=>$Step,layer=>$ref_layer,units=>'mm',surface=>1);
my @guard_warning=();
my (%max1,%max2);
foreach my $surface (@features1){
my $f =$ATS_GenMath->Polygon_Calculate_getArea(polygon=>\@{$surface->{feats}},tol=>'0.1',mode=> 'surface');
$f = sprintf "%0.4f",$f;
next if ($f==0);
my $ratio=sprintf "%0.3f",($f/$copper_a)*100;
my $ratio1=sprintf "%0.3f",($f/$f_all)*100;
$max1{$f}=$ratio;
$max2{$f}=$ratio1;
if ($ratio >= $percent ) {
my $Center = $ATS_GenMath->Calculate_Surface_Center(polygon=>\@{$surface->{feats}},precision=>'1',units=>'mm');
push @guard_warning ,"Exposed Pad Size all Area :${f_all}mm2 ,Single Area:${f}mm2;Ratio:[$ratio%].Pad Point :X:$Center->{1}{x}mm,Y:$Center->{1}{y}mm
";
$condition1= 'ok';
}
}
#$GUI->debug("$condition1 $condition2 $all_ratio");
if ($condition1 eq 'ok' or $condition2 eq 'ok'){
my ($max1) = sort {$b <=> $a} %max1;
$guard_warning1{1}="The Max exposed pad area: ${max1} mm2 ; Ratio: $max1{$max1}%";
$guard_warning1{2}="All exposed pad area: ${f_all} mm2 ; Ratio: $all_ratio%";
if (@guard_warning1) {
push @{$guard_warning1{3}},@guard_warning1;
}
push @{$guard_warning1{3}},@guard_warning if ($condition1 eq 'ok');
}
return \%guard_warning1;
}
sub exposed_pad_size1{
my $Job=shift;
my $Step= shift;
my $layer= shift;
my $ref_layer=shift;
my $base_on =shift;
my $f_all;
$GEN->openStep(job=>$Job,name=>$Step);
$GEN->units(type=>'mm');
$GEN->workLayer(name=>$ref_layer,display_number=>1,clear_before=>'yes');
$GEN->COM("sel_contourize,accuracy=0,break_to_islands=yes,clean_hole_size=0,clean_hole_mode=x_and_y");
$GEN->COM("sel_clean_surface,accuracy=10,clean_size=75,clean_mode=x_or_y,max_fold_len=0");
$f_all =$GEN->copperArea(
'layer1'=>$ref_layer,
'layer2'=>'',
'drills'=>'no',
'consider_rout'=>'no',
'drills_source'=>'matrix',
'drills_list'=>'',
'thickness'=>'1',
'resolution_value'=>10,
'x_boxes'=>3,
'y_boxes'=>3,
'area'=>'no',
'dist_map'=>'yes'
);
$f_all = sprintf "%0.4f",$f_all->{area};
my @features1 = $GEN->getFeatures(job=>$Job,step=>$Step,layer=>$ref_layer,units=>'mm',surface=>1);
my $guard_Area= 400;#mm
my $percent =35;
my @guard_warning=();
foreach my $surface (@features1){
my $f =$ATS_GenMath->Polygon_Calculate_getArea(polygon=>\@{$surface->{feats}},tol=>'0.1',mode=> 'surface');
$f = sprintf "%0.4f",$f;
next if ($f==0);
my $ratio=sprintf "%0.3f",($f/$f_all)*100;
if ($f >$guard_Area or $ratio > $percent) {
my $Center = $ATS_GenMath->Calculate_Surface_Center(polygon=>\@{$surface->{feats}},precision=>'1',units=>'mm');
push @guard_warning ,"Exposed Pad Size all Area :${f_all}mm2 ,Single Area:${f}mm2;Ratio:[$ratio%].Pad Point :X:$Center->{1}{x}mm,Y:$Center->{1}{y}mm";
}
}
return \@guard_warning;
}
sub polygon_surface{
my $Job=shift;
my $Step= shift;
my $layer= shift;
my $options = shift;#select
my $units= shift;
my $cshfile;
$cshfile=$GEN->INFO('entity_type'=>'layer',
'entity_path'=>"$Job/$Step/$layer",
'data_type'=>'FEATURES',
'parse'=>'no',
units=>$units,
) if (!$options);
$cshfile=$GEN->INFO('entity_type'=>'layer',
'entity_path'=>"$Job/$Step/$layer",
'data_type'=>'FEATURES',
'parse'=>'no',
options=>$options,
units=>$units,
) if ($options);
open(CSHFILE,"$cshfile");
my @polygon=;
close(CSHFILE);
shift @polygon;
return @polygon;
}
sub mail_sand_task {
my %par = @_; ## subject ##body ## title
my $mailinfo=$DB->select_hash(-table=>'ats_mail_sand_task',-where=>{mail_title=>$par{title}});
if ($mailinfo->{status} eq 'Start'){
my $mail_to=$mailinfo->{mail_to};
my $mail_cc=$mailinfo->{mail_cc};
if ($mail_to=~/^sub/){
$mail_to=eval($mail_to);
$mail_to= $mail_to->(job_id=>$JOB_ID);
}
else{
$mail_to=eval($mail_to) if ($mail_to=~/^\$/);
}
if ($mail_cc=~/^sub/){
$mail_cc=eval($mail_cc);
$mail_cc= $mail_cc->(job_id=>$JOB_ID);
}
else{
$mail_cc=eval($mail_cc) if ($mail_cc=~/^\$/);
}
my @to = split(/\;|\:|\,|\n/,$mail_to);
foreach my $it (@to){
$it =~ s/(^\s+|\s+$)//g;
}
$par{-to} = \@to;
#$data{cc} =~ s/\s+//g;
my @cc = split(/\;|\:|\,|\n/,$mail_cc);
foreach my $it (@cc){
$it =~ s/(^\s+|\s+$)//g;
}
$par{-cc} = \@cc;
$par{cc_user}='';
$par{group}='';
#$GUI->debug("@to m @cc ");
my $subject=$par{subject};
my $body = $par{body};
my $mail_version = $DB->select_value(
-table=>'ats_auto_mail_record',
-field=>'max(mail_version)',
-where=>"job_id = $JOB_ID and mail_title = '$par{title}'",
);
$mail_version = 0 unless ($mail_version);
$mail_version++;
my $resart_mail= 'yes';
if ($mail_version > 1 and $par{sand_mode} ne 'always' ){
my $tmp_v=$mail_version-1;
my $mail_subject = $DB->select_value(
-table=>'ats_auto_mail_record',
-field=>'mail_subject',
-where=>"job_id = $JOB_ID and mail_title = '$par{title}' and mail_version = $tmp_v",
);
my $mail_body = $DB->select_value(
-table=>'ats_auto_mail_record',
-field=>'mail_content',
-where=>"job_id = $JOB_ID and mail_title = '$par{title}' and mail_version = $tmp_v",
);
if ($mail_subject eq $subject){
$resart_mail='no';
if ($mail_body ne $body){
$resart_mail='yes';
}
}
elsif ($mail_body ne $body){
$resart_mail='yes';
}
}
#$GUI->debug(dump\%par);
#exit;
if ($resart_mail eq 'yes'){
Top::MailSender->send_mail(%par);
my ($content,$att);
if (ref $par{body} eq 'ARRAY') {
($content,$att) = @{$par{body}};
}
else {
$content = $par{body};
}
if ($att) {
my @att = @{$att};
if (@att) {
$att = join(',',@att);
$att = '' unless ($att);
}else {
$att = '';
}
}
else {
$att = '';
}
$DB->insert(
-table=>'ats_auto_mail_record',
-data=>{
job_id => $JOB_ID,
mail_from=>$APP->{USER_NAME},
mail_to=>$mail_to,
mail_cc=>$mail_cc,
mail_subject=>$par{subject},
mail_title=>$par{title},
mail_content=>$content,
mail_attachment=>$att,
mail_version=>$mail_version,
}
);
}
}
}
sub calc_area{
my $output_layer=shift;
$GEN->COM('chklist_single,action=ats_analysis_calc_area,show=no');
$GEN->COM("chklist_cupd,chklist=ats_analysis_calc_area,nact=1,params=((pp_layer=.affected)(pp_output_layer=$output_layer)(pp_flatten_mode=Yes)),mode=regular");
$GEN->COM('chklist_run,chklist=ats_analysis_calc_area,nact=1,area=profile');
}
sub INCAM_CreateMetalLayer{
my %par = @_;
my $outputLayer=$par{outputLayer};
my $ep = $par{ep};
my $sm = $par{sm};
my $tmp_ep = "script_".$ep;
my $tmp_sm = "script_".$sm;
my $step = $par{step};
$GEN->copyLayer(source_job=>$Job,source_step=>$step,source_layer=>$ep,dest_layer=>$tmp_ep);
$GEN->copyLayer(source_job=>$Job,source_step=>$step,source_layer=>$sm,dest_layer=>$tmp_sm);
$GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>[$tmp_ep,$tmp_sm],clear_before=>'yes');
$GEN->selContourize();
$GEN->COM("sel_feat2outline,width=0,location=on_edge,offset=0,polarity=as_feature,keep_original=no,text2limit=no");
$GEN->COM("sel_cut_data,det_tol=1,con_tol=1,rad_tol=0,ignore_width=yes,filter_overlaps=no,delete_doubles=no,use_order=yes,ignore_holes=none,start_positive=yes,polarity_of_touching=same,contourize=yes,simplify=yes,resize_thick_lines=no");
$GEN->COM("rv_tab_view_results_enabled,report=cut_data_rep,is_enabled=no,serial_num=-1,all_count=-1");
$GEN->copyLayer(source_job=>$Job,source_step=>$step,source_layer=>$tmp_sm,dest_layer=>$outputLayer);
$GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>[$tmp_sm],clear_before=>'yes');
$GEN->COM("sel_resize,size=0.5,corner_ctl=no");
$GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>[$tmp_ep],clear_before=>'yes');
$GEN->selCopyOther(dest=>'layer_name',target_layer=>$tmp_sm,invert=>'yes',size=>0.5);
$GEN->workLayer(name=>$tmp_sm,display_number=>1,clear_before=>'yes');
$GEN->COM("sel_contourize,accuracy=0,break_to_islands=yes,clean_hole_size=0,clean_hole_mode=x_and_y");
$GEN->selCopyOther(dest=>'layer_name',target_layer=>$outputLayer,invert=>'yes',size=>0.5);
$GEN->workLayer(name=>$outputLayer,display_number=>1,clear_before=>'yes');
$GEN->selContourize();
_deleteLayer(job=>$Job,step=>$step,layer=>[$tmp_ep,$tmp_sm]);
}