| | |
| | | m_pCclink = nullptr; |
| | | m_nBaseAlarmId = 0; |
| | | m_pArm = nullptr; |
| | | m_processState = PROCESS_STATE::Ready; |
| | | InitializeCriticalSection(&m_criticalSection); |
| | | } |
| | | |
| | |
| | | pStep->setCcLink(m_pCclink); |
| | | m_mapStep[addr] = pStep; |
| | | return 0; |
| | | } |
| | | |
| | | void CEquipment::setProcessState(PROCESS_STATE state) |
| | | { |
| | | m_processState = state; |
| | | onProcessStateChanged(m_processState); |
| | | |
| | | if (m_listener.onProcessStateChanged != nullptr) { |
| | | m_listener.onProcessStateChanged(this, m_processState); |
| | | } |
| | | } |
| | | |
| | | void CEquipment::init() |
| | |
| | | m_bLinkSignal[i][SIGNAL_SEND_ABLE] = isBitOn(pszData, size, index + 3); |
| | | index += 0x40; |
| | | } |
| | | |
| | | if(m_bLinkSignal[0][SIGNAL_SEND_ABLE]) { |
| | | onSendAble(); |
| | | } |
| | | |
| | | // 其它信号及响应 |
| | | index = 0x540; |
| | |
| | | |
| | | // robot cmd reply |
| | | CHECK_WRITE_STEP_SIGNAL(STEP_ID_ROBOT_CMD_REPLY, pszData, size); |
| | | |
| | | |
| | | // Indexer Operation Mode Change |
| | | CHECK_WRITE_STEP_SIGNAL(STEP_ID_IN_OP_CMD_REPLY, pszData, size); |
| | | } |
| | | |
| | | BOOL CEquipment::isBitOn(const char* pszData, size_t size, int index) |
| | |
| | | CGlass* pContext = nullptr; |
| | | for (int i = 0; i < SLOT_MAX; i++) { |
| | | CGlass* pGlass = (CGlass*)m_slot[i].getContext(); |
| | | if (pGlass != nullptr && compareJobDataB(pJobDataB, pGlass->getJobDataB())) { |
| | | if (pGlass != nullptr && compareJobData(pJobDataB, pGlass->getJobDataS())) { |
| | | pContext = pGlass; |
| | | if (pGlass != nullptr) pGlass->addRef(); |
| | | m_slot[i].setContext(nullptr); |
| | |
| | | ((CArm*)m_pArm)->tempStore(pContext); |
| | | pContext->release(); |
| | | Unlock(); |
| | | |
| | | |
| | | if (m_processState != PROCESS_STATE::Ready) { |
| | | setProcessState(PROCESS_STATE::Ready); |
| | | } |
| | | |
| | | if (m_listener.onDataChanged != nullptr) { |
| | | m_listener.onDataChanged(this, EDCC_FETCHOUT_JOB); |
| | |
| | | pGlass->release(); // tempFetchOut需要调用一次release |
| | | Unlock(); |
| | | |
| | | |
| | | // 如果此玻璃已经贴合,贴合的玻璃也要从加入到列表中 |
| | | /* |
| | | CGlass* pBuddy = pGlass->getBuddy(); |
| | | if (pBuddy != nullptr) { |
| | | Lock(); |
| | | pBuddy->addPath(m_nID, 0); |
| | | if (putSlot % 2 == 0) { |
| | | m_slot[putSlot - 2].setContext(pBuddy); |
| | | } |
| | | else { |
| | | m_slot[putSlot].setContext(pBuddy); |
| | | } |
| | | Unlock(); |
| | | if (m_processState != PROCESS_STATE::Processing) { |
| | | setProcessState(PROCESS_STATE::Processing); |
| | | } |
| | | */ |
| | | |
| | | if (m_listener.onDataChanged != nullptr) { |
| | | m_listener.onDataChanged(this, EDCC_STORED_JOB); |
| | |
| | | return pGlass; |
| | | } |
| | | } |
| | | |
| | | return nullptr; |
| | | } |
| | | |
| | | CGlass* CEquipment::getGlassFromSlot(int slotNo) |
| | | { |
| | | CSlot* pSlot = nullptr; |
| | | for (int i = 0; i < SLOT_MAX; i++) { |
| | | if (!m_slot[i].isEnable()) continue; |
| | | if (m_slot[i].getNo() != slotNo) continue; |
| | | pSlot = &m_slot[i]; |
| | | break; |
| | | } |
| | | |
| | | if (pSlot != nullptr) { |
| | | return (CGlass*)pSlot->getContext(); |
| | | } |
| | | |
| | | return nullptr; |
| | | } |
| | | |
| | | CGlass* CEquipment::getGlassWithCassette(int cassetteSequenceNo, int jobSequenceNo) |
| | | { |
| | | CSlot* pSlot = nullptr; |
| | | for (int i = 0; i < SLOT_MAX; i++) { |
| | | if (!m_slot[i].isEnable()) continue; |
| | | CGlass* pGlass = (CGlass*)m_slot[i].getContext(); |
| | | if (pGlass == nullptr) continue; |
| | | CJobDataS* pJobDataS = pGlass->getJobDataS(); |
| | | ASSERT(pJobDataS); |
| | | if (pJobDataS->getCassetteSequenceNo() == cassetteSequenceNo |
| | | && pJobDataS->getJobSequenceNo() == jobSequenceNo) { |
| | | return pGlass; |
| | | } |
| | | } |
| | | |
| | | |
| | | return nullptr; |
| | | } |
| | | |
| | | CJobDataS* CEquipment::getJobDataSWithCassette(int cassetteSequenceNo, int jobSequenceNo) |
| | | { |
| | | CSlot* pSlot = nullptr; |
| | | for (int i = 0; i < SLOT_MAX; i++) { |
| | | if (!m_slot[i].isEnable()) continue; |
| | | CGlass* pGlass = (CGlass*)m_slot[i].getContext(); |
| | | if (pGlass == nullptr) continue; |
| | | CJobDataS* pJobDataS = pGlass->getJobDataS(); |
| | | ASSERT(pJobDataS); |
| | | if (pJobDataS->getCassetteSequenceNo() == cassetteSequenceNo |
| | | && pJobDataS->getJobSequenceNo() == jobSequenceNo) { |
| | | return pJobDataS; |
| | | } |
| | | } |
| | | |
| | | |
| | | return nullptr; |
| | | } |
| | |
| | | return 0; |
| | | } |
| | | |
| | | int CEquipment::indexerOperationModeChange(IDNEXER_OPERATION_MODE mode, ONWRITED onWritedBlock/* = nullptr*/) |
| | | int CEquipment::indexerOperationModeChange(IDNEXER_OPERATION_MODE mode, ONWRITEDRET onWritedRetBlock) |
| | | { |
| | | SERVO::CEqWriteStep* pStep = (SERVO::CEqWriteStep*)getStepWithName(STEP_EFEM_IN_OP_MODE_CHANGE); |
| | | SERVO::CEqWriteStep* pStep = (SERVO::CEqWriteStep*)getStepWithName(STEP_EQ_IN_OP_MODE_CHANGE); |
| | | if (pStep == nullptr) { |
| | | return -1; |
| | | } |
| | | |
| | | unsigned short operationMode = (unsigned short)((unsigned short)mode + getIndexerOperationModeBaseValue()); |
| | | LOGI("<CEquipment-%s>准备设置indexerOperationMode<%d>", m_strName.c_str(), (int)mode); |
| | | if (onWritedBlock != nullptr) { |
| | | pStep->writeShort(operationMode, onWritedBlock); |
| | | } |
| | | else { |
| | | pStep->writeShort(operationMode, [&, mode](int code) -> int { |
| | | if (code == WOK) { |
| | | LOGI("<CEquipment-%s>设置indexerOperationMode成功.", m_strName.c_str()); |
| | | } |
| | | else { |
| | | LOGI("<CEquipment-%s>设置indexerOperationMode失败,code:%d", m_strName.c_str(), code); |
| | | } |
| | | pStep->writeShort(operationMode, [&, pStep, mode, onWritedRetBlock](int code) -> int { |
| | | int retCode = 0; |
| | | if (code == WOK) { |
| | | LOGI("<CEquipment-%s>设置indexerOperationMode成功.", m_strName.c_str()); |
| | | const char* pszRetData = nullptr; |
| | | pStep->getReturnData(pszRetData); |
| | | ASSERT(pszRetData); |
| | | retCode = (unsigned int)CToolUnits::toInt16(pszRetData); |
| | | LOGI("<CEquipment-%s>返回值: %d", m_strName.c_str(), retCode); |
| | | } |
| | | else { |
| | | LOGI("<CEquipment-%s>设置indexerOperationMode失败,code:%d", m_strName.c_str(), code); |
| | | } |
| | | |
| | | return 0; |
| | | }); |
| | | } |
| | | if (onWritedRetBlock != nullptr) { |
| | | onWritedRetBlock(code, retCode); |
| | | } |
| | | |
| | | return 0; |
| | | }); |
| | | |
| | | return 0; |
| | | } |
| | |
| | | return &m_slot[index]; |
| | | } |
| | | |
| | | CGlass* CEquipment::getGlassFromSlot(int slotNo) |
| | | { |
| | | CSlot* pSlot = nullptr; |
| | | for (int i = 0; i < SLOT_MAX; i++) { |
| | | if (!m_slot[i].isEnable()) continue; |
| | | if (m_slot[i].getNo() != slotNo) continue; |
| | | pSlot = &m_slot[i]; |
| | | break; |
| | | } |
| | | |
| | | if (pSlot != nullptr) { |
| | | return (CGlass*)pSlot->getContext(); |
| | | } |
| | | |
| | | return nullptr; |
| | | } |
| | | |
| | | CGlass* CEquipment::getAnyGlass() |
| | | { |
| | | CSlot* pSlot = nullptr; |
| | |
| | | int CEquipment::onReceivedJob(int port, CJobDataS* pJobDataS) |
| | | { |
| | | LOGI("<CEquipment-%s>onReceivedJob.", m_strName.c_str()); |
| | | |
| | | addJobDataS(pJobDataS); |
| | | return 0; |
| | | } |
| | | |
| | |
| | | pStep->addAttributeVector(attrubutes); |
| | | |
| | | |
| | | onReceivedJob(port, &jobDataS); |
| | | onSentOutJob(port, &jobDataS); |
| | | |
| | | return nRet; |
| | | } |
| | |
| | | { |
| | | LOGI("<CEquipment-%s>onSentOutJob.", m_strName.c_str()); |
| | | |
| | | int count = removeJobDataS(pJobDataS->getCassetteSequenceNo(), pJobDataS->getJobSequenceNo()); |
| | | if (count == 1) { |
| | | LOGI("<CEquipment-%s>onSentOutJob,删除数据 %d 条", m_strName.c_str(), count); |
| | | |
| | | // 可以在此更新JobDataS数据了 |
| | | CGlass* pGlass = getGlass(pJobDataS->getGlass1Id().c_str()); |
| | | if (pGlass == nullptr) { |
| | | LOGE("<CEquipment-%s>onSentOutJob,没有找到对应的Glass(CassetteSequenceNo:%d, JobSequenceNo:%d, ID=%s),请检查数据,注意风险。", |
| | | m_strName.c_str(), pJobDataS->getCassetteSequenceNo(), pJobDataS->getJobSequenceNo(), |
| | | pJobDataS->getGlass1Id().c_str()); |
| | | return -1; |
| | | } |
| | | else { |
| | | LOGE("<CEquipment-%s>onSentOutJob,删除数据 %d 条,注意排查风险", m_strName.c_str(), count); |
| | | } |
| | | pGlass->updateJobDataS(pJobDataS); |
| | | |
| | | return 0; |
| | | } |
| | |
| | | return 0; |
| | | } |
| | | |
| | | int CEquipment::decodePanelDataRequest(CStep* pStep, const char* pszData, size_t size) |
| | | { |
| | | int index = 0; |
| | | short cassetteSequenceNo, jobSequenceNo; |
| | | memcpy(&cassetteSequenceNo, &pszData[index], sizeof(short)); |
| | | index += sizeof(short); |
| | | memcpy(&jobSequenceNo, &pszData[index], sizeof(short)); |
| | | index += sizeof(short); |
| | | |
| | | |
| | | // efme, 获取数据后返回 |
| | | // Cassette Sequence No 1W |
| | | // Job Sequence No 1W |
| | | // Job DataS 256W |
| | | char szBuffer[1024]; |
| | | index = 0; |
| | | memcpy(&szBuffer[index], &cassetteSequenceNo, sizeof(short)); |
| | | index += sizeof(short); |
| | | memcpy(&szBuffer[index], &jobSequenceNo, sizeof(short)); |
| | | index += sizeof(short); |
| | | |
| | | CJobDataS* pJobDataS = getJobDataSWithCassette(cassetteSequenceNo, jobSequenceNo); |
| | | if (pJobDataS != nullptr) { |
| | | index += pJobDataS->serialize(&szBuffer[index], 1024 - sizeof(short) - sizeof(short)); |
| | | ((CEqReadStep*)pStep)->setReturnData(szBuffer, index); |
| | | } |
| | | |
| | | |
| | | // 缓存Attribute,用于调试时显示信息 |
| | | unsigned int weight = 201; |
| | | pStep->addAttribute(new CAttribute("CassetteSequenceNo", |
| | | (std::to_string(cassetteSequenceNo)).c_str(), "", weight++)); |
| | | pStep->addAttribute(new CAttribute("JobSequenceNo", |
| | | (std::to_string(jobSequenceNo)).c_str(), "", weight++)); |
| | | |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int CEquipment::onPreStoredJob(int port, CJobDataB* pJobDataB, short& putSlot) |
| | | { |
| | | LOGI("<CEquipment-%s>onPreStoredJob:port:%d|GlassId:%s", |
| | | m_strName.c_str(), port, pJobDataB->getGlassId().c_str()); |
| | | |
| | | CJobDataS* pJobDataS = getJobDataS(pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo()); |
| | | if (pJobDataS == nullptr) { |
| | | LOGE("<CFliper-%s>onPreFetchedOutJob,找不到对应的JobDataS(CassetteSequenceNo:%d, JobSequenceNo:%d), 注意排查风险!", m_strName.c_str(), |
| | | // 当前要存片,之前肯定有拔片,因此片子在Arm那里 |
| | | CGlass* pGlass = ((CArm*)m_pArm)->getGlassFromSlot(1); |
| | | if (pGlass == nullptr) { |
| | | LOGE("<CFliper-%s>onPreStoredJob,缓存中没有找到对应的Glass(CassetteSequenceNo:%d, JobSequenceNo:%d),请检查数据,注意风险。", m_strName.c_str(), |
| | | pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo()); |
| | | return FALSE; |
| | | } |
| | | |
| | | CJobDataS* pJobDataS = pGlass->getJobDataS(); |
| | | ASSERT(pJobDataS); |
| | | if (!compareJobData(pJobDataB, pJobDataS)) { |
| | | LOGE("<CFliper-%s>onPreFetchedOutJob,JobData数据不匹配(JobDataB(%d, %d),JobDataS(%d, %d)), 注意排查风险!", m_strName.c_str(), |
| | | pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo(), |
| | | pJobDataS->getCassetteSequenceNo(), pJobDataS->getJobSequenceNo()); |
| | | return FALSE; |
| | | } |
| | | |
| | |
| | | short putSlot = 0; |
| | | BOOL bCheck = onPreStoredJob(port, pJobDataB, putSlot); |
| | | if (bCheck) { |
| | | addJobDataB(pJobDataB); |
| | | return storedJob(pJobDataB, putSlot); |
| | | } |
| | | |
| | |
| | | return 0; |
| | | } |
| | | |
| | | /* |
| | | * 当从CC-Link检测到设备Send Able为On时调用此函数 |
| | | * 可能会多次重复调用(根据扫描频率), 注意防呆 |
| | | */ |
| | | int CEquipment::onSendAble() |
| | | { |
| | | LOGI("<CEquipment-%s>onSendAble.", m_strName.c_str()); |
| | | |
| | | if (m_processState != PROCESS_STATE::Complete) { |
| | | setProcessState(PROCESS_STATE::Complete); |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int CEquipment::onProcessStateChanged(PROCESS_STATE state) |
| | | { |
| | | return 0; |
| | | } |
| | | |
| | | int CEquipment::getIndexerOperationModeBaseValue() |
| | | { |
| | | return 0; |
| | | } |
| | | |
| | | int CEquipment::addJobDataB(CJobDataB* pJobDataB) |
| | | BOOL CEquipment::compareJobData(CJobDataB* pJobDataB, CJobDataS* pJobDataS) |
| | | { |
| | | // 添加之前先删除旧的,以免数据重复 |
| | | Lock(); |
| | | int count = removeJobDataB(pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo()); |
| | | if (count > 0) { |
| | | LOGE("<CEquipment-%s>addJobDataB,删除重复数据 %d 条,注意排查风险", m_strName.c_str(), count); |
| | | } |
| | | ASSERT(pJobDataB); |
| | | ASSERT(pJobDataS); |
| | | |
| | | m_listJobDataB.push_back(std::move(*pJobDataB)); |
| | | Unlock(); |
| | | |
| | | return (int)m_listJobDataB.size(); |
| | | } |
| | | |
| | | int CEquipment::removeJobDataB(int nCassetteSequenceNo, int nJobSequenceNo) |
| | | { |
| | | int count = 0; |
| | | for (auto it = m_listJobDataB.begin(); it != m_listJobDataB.end(); ) { |
| | | if ((*it).getCassetteSequenceNo() == nCassetteSequenceNo |
| | | && (*it).getJobSequenceNo() == nJobSequenceNo) { |
| | | it = m_listJobDataB.erase(it); |
| | | count++; |
| | | } |
| | | else { |
| | | ++it; |
| | | } |
| | | } |
| | | |
| | | return count; |
| | | } |
| | | |
| | | CJobDataB* CEquipment::getJobDataB(int nCassetteSequenceNo, int nJobSequenceNo) |
| | | { |
| | | for (auto& item : m_listJobDataB) { |
| | | if (item.getCassetteSequenceNo() == nCassetteSequenceNo |
| | | && item.getJobSequenceNo() == nJobSequenceNo) { |
| | | return &item; |
| | | } |
| | | } |
| | | |
| | | return nullptr; |
| | | } |
| | | |
| | | int CEquipment::addJobDataS(CJobDataS* pJobDataS) |
| | | { |
| | | // 添加之前先删除旧的,以免数据重复 |
| | | Lock(); |
| | | int count = removeJobDataS(pJobDataS->getCassetteSequenceNo(), pJobDataS->getJobSequenceNo()); |
| | | if (count > 0) { |
| | | LOGE("<CEquipment-%s>addJobDataS,删除重复数据 %d 条,注意排查风险", m_strName.c_str(), count); |
| | | } |
| | | |
| | | m_listJobDataS.push_back(std::move(*pJobDataS)); |
| | | Unlock(); |
| | | |
| | | return (int)m_listJobDataB.size(); |
| | | } |
| | | |
| | | int CEquipment::removeJobDataS(int nCassetteSequenceNo, int nJobSequenceNo) |
| | | { |
| | | int count = 0; |
| | | Lock(); |
| | | for (auto it = m_listJobDataS.begin(); it != m_listJobDataS.end(); ) { |
| | | if ((*it).getCassetteSequenceNo() == nCassetteSequenceNo |
| | | && (*it).getJobSequenceNo() == nJobSequenceNo) { |
| | | it = m_listJobDataS.erase(it); |
| | | count++; |
| | | } |
| | | else { |
| | | ++it; |
| | | } |
| | | } |
| | | Unlock(); |
| | | |
| | | return count; |
| | | } |
| | | |
| | | CJobDataS* CEquipment::getJobDataS(int nCassetteSequenceNo, int nJobSequenceNo) |
| | | { |
| | | for (auto& item : m_listJobDataS) { |
| | | if (item.getCassetteSequenceNo() == nCassetteSequenceNo |
| | | && item.getJobSequenceNo() == nJobSequenceNo) { |
| | | return &item; |
| | | } |
| | | } |
| | | |
| | | return nullptr; |
| | | } |
| | | |
| | | BOOL CEquipment::compareJobDataB(CJobDataB* pJobDataB1, CJobDataB* pJobDataB2) |
| | | { |
| | | ASSERT(pJobDataB1); |
| | | ASSERT(pJobDataB2); |
| | | |
| | | if (pJobDataB1->getCassetteSequenceNo() != pJobDataB2->getCassetteSequenceNo()) |
| | | if (pJobDataB->getCassetteSequenceNo() != pJobDataS->getCassetteSequenceNo()) |
| | | return FALSE; |
| | | if (pJobDataB1->getJobSequenceNo() != pJobDataB2->getJobSequenceNo()) |
| | | if (pJobDataB->getJobSequenceNo() != pJobDataS->getJobSequenceNo()) |
| | | return FALSE; |
| | | |
| | | return TRUE; |