|
|
#include "manage.h"
|
|
|
#include "log.h"
|
|
|
#include "var.h"
|
|
|
#include "ops.h"
|
|
|
#include "test.h"
|
|
|
#include "control.h"
|
|
|
|
|
|
//CProduct类实现
|
|
|
CProduct::CProduct(int sindex)
|
|
|
{
|
|
|
_t1 = _t2 = _t3 = 0;
|
|
|
memset(&data, 0, sizeof(data));
|
|
|
data.pos = (EMapPos)sindex;
|
|
|
comm_strcpy(data.lot, ins->getLot());
|
|
|
}
|
|
|
|
|
|
void CProduct::Clear()
|
|
|
{
|
|
|
memset(&data, 0, sizeof(data));
|
|
|
data.pos = LocationInput;
|
|
|
comm_strcpy(data.lot, ins->getLot());
|
|
|
}
|
|
|
|
|
|
char* CProduct::Ate()
|
|
|
{
|
|
|
switch (data.count)
|
|
|
{
|
|
|
case 2:
|
|
|
return data.ate2;
|
|
|
case 3:
|
|
|
return data.ate3;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
return data.ate1; //最后到B组,ate放到第1个,保证留着最后一个记录
|
|
|
}
|
|
|
|
|
|
void CProduct::SetIndex(int t)
|
|
|
{
|
|
|
switch (data.count)
|
|
|
{
|
|
|
case 2:
|
|
|
_t2 = t;
|
|
|
return;
|
|
|
case 3:
|
|
|
_t3 = t;
|
|
|
return;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
_t1 = t; //最后到B组,ate放到第1个,保证留着最后一个记录
|
|
|
}
|
|
|
|
|
|
int CProduct::lastIndex()
|
|
|
{//最后一次治具序号
|
|
|
switch (data.count)
|
|
|
{
|
|
|
case 2:
|
|
|
return _t2;
|
|
|
case 3:
|
|
|
return _t3;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
return _t1; //最后到B组,ate放到第1个,保证留着最后一个记录
|
|
|
}
|
|
|
|
|
|
const char* CProduct::LastAte()
|
|
|
{
|
|
|
switch (data.count)
|
|
|
{
|
|
|
case 2:
|
|
|
return data.ate2;
|
|
|
case 3:
|
|
|
return data.ate3;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
return data.ate1; //最后到B组,ate放到第1个,保证留着最后一个记录
|
|
|
}
|
|
|
|
|
|
cstr getRetryModel(int count)
|
|
|
{
|
|
|
switch (count)
|
|
|
{
|
|
|
case 1:
|
|
|
return "T1";
|
|
|
case 2:
|
|
|
return "R1";
|
|
|
case 3:
|
|
|
return "R2";
|
|
|
case 4:
|
|
|
return "R3";
|
|
|
case 5:
|
|
|
return "R4";
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
return "Rn";
|
|
|
}
|
|
|
|
|
|
cstr CProduct::getRetryModelS()
|
|
|
{
|
|
|
return getRetryModel(data.count + 1);
|
|
|
}
|
|
|
|
|
|
cstr CProduct::getRetryModelE()
|
|
|
{
|
|
|
return getRetryModel(data.count);
|
|
|
}
|
|
|
|
|
|
bool CProduct::CanTestAAB(const char* ate)
|
|
|
{//AAB模式,是否可以用这个ate测试
|
|
|
if (0 == data.count) return true;
|
|
|
return 1 == data.count
|
|
|
? strcmp(data.ate1, ate) ? false : true //第二次必须放到第一次的治具
|
|
|
: strcmp(LastAte(), ate) ? true : false; //其它必须放在不同的治具
|
|
|
}
|
|
|
|
|
|
bool CProduct::CanTestABC(const char* ate)
|
|
|
{//ABC模式,是否可以用这个ate测试
|
|
|
if (0 == data.count) return true;
|
|
|
if (1 == data.count)
|
|
|
{
|
|
|
return strcmp(data.ate1, ate) ? true : false;
|
|
|
}
|
|
|
if (2 == data.count)
|
|
|
{
|
|
|
return strcmp(data.ate1, ate) && strcmp(data.ate2, ate) ? true : false;
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
bool CManage::NeedTestDual(CProduct* p, int t)
|
|
|
{//是否需要继续测试 -- 可尝试传入治具判断是否可以在该治具复测
|
|
|
int x = 0;
|
|
|
int aend = m_pEnda->geti();
|
|
|
|
|
|
if (p->IsSameBin(getBinA())) return false; //与设置Bin信息相同,不再测试
|
|
|
if (p->lastIndex() > aend) return false; //已经进B组测试
|
|
|
if (p->NeedTest()) return t <= aend ? true : false; //需要A组重测 -- 若传入B组t,则返回false
|
|
|
if (aend >= TESTCNT) return false; //当前是单组模式
|
|
|
if (!p->IsOk() && IsPassToB()) return false; //NG不进B组
|
|
|
if (IsBindTest())
|
|
|
{//绑定模式
|
|
|
x = p->lastIndex() + aend;
|
|
|
if (x > TESTCNT) return false;
|
|
|
if (!m_ptest[x - 1]->Enabled()) return false;
|
|
|
if (!m_ptest[x - 1]->IsReady()) return false;
|
|
|
return (t && t != x) ? false : true; //不在当前治具
|
|
|
}
|
|
|
|
|
|
//if (t > aend && t <= TESTCNT &&
|
|
|
// m_ptest[t - 1]->Enabled() &&
|
|
|
// m_ptest[t - 1]->IsReady())
|
|
|
//{//治具编号有效
|
|
|
// return true;
|
|
|
//}
|
|
|
|
|
|
//非绑定模式 -- 看B组是否有就绪治具空闲
|
|
|
if (t > aend) return true; //传入说明该治具已经就绪
|
|
|
for (int i = aend; i < TESTCNT; i++)
|
|
|
{//看下B组是否就绪
|
|
|
if (!m_ptest[i]->Enabled()) continue; //未启用
|
|
|
if (!m_ptest[i]->IsReady()) continue; //不在就绪状态
|
|
|
t = i + 1;
|
|
|
return true; //空闲
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
int CManage::FindTestDual(CProduct* p, bool bchkp, int aend)
|
|
|
{//查找可以放的治具 -- 双测模式
|
|
|
int t = 0;
|
|
|
if (p->NeedTest(getBinA()))
|
|
|
{//还需要在A组测试
|
|
|
return FindTest(p, bchkp, aend);
|
|
|
}
|
|
|
|
|
|
//下面两行代码可以注释,NeedTestDual()已经判断了
|
|
|
//if (!p->IsOk() && IsPassToB()) return 0; //NG不进B组
|
|
|
//if (p->lastIndex() > aend) return 0; //已经进B组测试
|
|
|
if (IsBindTest())
|
|
|
{//绑定模式
|
|
|
t = p->lastIndex() + aend;
|
|
|
if (t > TESTCNT) return 0;
|
|
|
if (bchkp && m_ptest[t - 1]->_p) return 0; //检测有料
|
|
|
if (!m_ptest[t - 1]->Enabled()) return 0;
|
|
|
if (!m_ptest[t - 1]->IsReady()) return 0;
|
|
|
return t;
|
|
|
}
|
|
|
|
|
|
//非绑定模式 -- 看B组是否有就绪治具空闲
|
|
|
for (int i = aend; i < TESTCNT; i++)
|
|
|
{//看下B组是否就绪
|
|
|
if (bchkp && m_ptest[i]->_p) continue; //检测有料
|
|
|
if (!m_ptest[i]->Enabled()) continue; //未启用
|
|
|
if (!m_ptest[i]->IsReady()) continue; //不在就绪状态
|
|
|
return i + 1; //空闲
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
void CManage::GetPutByTestB(int &v, int t, bool bchkp)
|
|
|
{//以当前t优先考虑,是否可以放入B组测试
|
|
|
for (int i = 0; i < m_vacm_cnt; i++)
|
|
|
{//吸嘴编号
|
|
|
if (!m_vacm_lst[i]) continue;
|
|
|
if (bchkp && m_ptest[t - 1]->_p) continue;
|
|
|
if (m_ptest[t - 1]->IsNextNoTest())
|
|
|
{//用于缓存 -- 直接可以
|
|
|
v = i + 1;
|
|
|
REPORT("set notest v = %d t = %d.", v, t);
|
|
|
//set_int_var("test", 1);
|
|
|
//ops_analog_signal(IOS_PAUSE, 1); //测试,暂停一下
|
|
|
break;
|
|
|
}
|
|
|
if (!NeedTestDual(m_vacm_lst[i], t)) continue; //不需要在B组测试
|
|
|
v = i + 1;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void CManage::GetTestPutDual(int &v, int &t, int aend, bool bchkp)
|
|
|
{//testput 通知设置需要进入治具的吸嘴编号->'v',治具编号->'t',为0时无效
|
|
|
v = 0;
|
|
|
if (t > 0 && t <= TESTCNT &&
|
|
|
m_ptest[t - 1]->Enabled() &&
|
|
|
m_ptest[t - 1]->IsReady())
|
|
|
{//治具编号有效
|
|
|
return t <= aend ? GetPutByTest(v, t, bchkp) : GetPutByTestB(v, t, bchkp);
|
|
|
}
|
|
|
|
|
|
for (int i = 0; i < m_vacm_cnt; i++)
|
|
|
{//吸嘴编号
|
|
|
if (!m_vacm_lst[i]) continue;
|
|
|
if (!NeedTestDual(m_vacm_lst[i])) continue; //不需要测试
|
|
|
t = FindTestDual(m_vacm_lst[i], bchkp, aend);
|
|
|
if (0 == t) continue; //未找到
|
|
|
v = i + 1;
|
|
|
break;
|
|
|
}
|
|
|
}
|