| | |
| | | #include "stdafx.h" |
| | | #include "Common.h" |
| | | #include "CMaster.h" |
| | | #include <future> |
| | | #include <vector> |
| | | |
| | | |
| | | namespace SERVO { |
| | |
| | | m_ullRunTime = 0; |
| | | m_state = MASTERSTATE::READY; |
| | | m_pActiveRobotTask = nullptr; |
| | | m_nLastError = 0; |
| | | InitializeCriticalSection(&m_criticalSection); |
| | | } |
| | | |
| | |
| | | ASSERT(pMeasurement); |
| | | |
| | | pEfem->setPort(0, pPort1); |
| | | pEfem->setPort(1, pPort1); |
| | | pEfem->setPort(2, pPort1); |
| | | pEfem->setPort(3, pPort1); |
| | | pEfem->setPort(1, pPort2); |
| | | pEfem->setPort(2, pPort3); |
| | | pEfem->setPort(3, pPort4); |
| | | pEfem->setFliper(pFliper); |
| | | pEfem->setAligner(pAligner); |
| | | pEfem->setArmTray(0, pArmTray1); |
| | |
| | | return 0; |
| | | } |
| | | |
| | | void CMaster::clearError() |
| | | { |
| | | m_nLastError = 0; |
| | | m_strLastError = ""; |
| | | setState(MASTERSTATE::READY); |
| | | } |
| | | |
| | | ULONGLONG CMaster::getRunTime() |
| | | { |
| | | if (m_state == MASTERSTATE::RUNNING) |
| | |
| | | |
| | | |
| | | // 各种机器 |
| | | CEFEM* pEFEM = (CEFEM*)getEquipment(EQ_ID_EFEM); |
| | | CLoadPort* pLoadPort1 = (CLoadPort*)getEquipment(EQ_ID_LOADPORT1); |
| | | CLoadPort* pLoadPort2 = (CLoadPort*)getEquipment(EQ_ID_LOADPORT2); |
| | | CLoadPort* pLoadPort3 = (CLoadPort*)getEquipment(EQ_ID_LOADPORT3); |
| | | CLoadPort* pLoadPort4 = (CLoadPort*)getEquipment(EQ_ID_LOADPORT4); |
| | | CFliper* pFliper = (CFliper*)getEquipment(EQ_ID_FLIPER); |
| | | CVacuumBake* pVacuumBack = (CVacuumBake*)getEquipment(EQ_ID_VACUUMBAKE); |
| | | CVacuumBake* pVacuumBake = (CVacuumBake*)getEquipment(EQ_ID_VACUUMBAKE); |
| | | CAligner* pAligner = (CAligner*)getEquipment(EQ_ID_ALIGNER); |
| | | CBonder* pBonder1 = (CBonder*)getEquipment(EQ_ID_Bonder1); |
| | | CBonder* pBonder2 = (CBonder*)getEquipment(EQ_ID_Bonder2); |
| | | CBakeCooling* pBakeCooling = (CBakeCooling*)getEquipment(EQ_ID_BAKE_COOLING); |
| | | CMeasurement* pMeasurement = (CMeasurement*)getEquipment(EQ_ID_MEASUREMENT); |
| | | |
| | | ASSERT(pEFEM); |
| | | ASSERT(pLoadPort1); |
| | | ASSERT(pLoadPort2); |
| | | ASSERT(pLoadPort3); |
| | | ASSERT(pLoadPort4); |
| | | ASSERT(pFliper); |
| | | ASSERT(pVacuumBack); |
| | | ASSERT(pVacuumBake); |
| | | ASSERT(pAligner); |
| | | ASSERT(pBonder1); |
| | | ASSERT(pBonder2); |
| | | ASSERT(pBakeCooling); |
| | | ASSERT(pMeasurement); |
| | | |
| | | while (1) { |
| | | // 待退出信号或时间到 |
| | |
| | | // 如果状态为STARTING,开始工作并切换到RUNNING状态 |
| | | lock(); |
| | | if (m_state == MASTERSTATE::STARTING) { |
| | | // 发送indexerOperationModeChange到各个机台,成功后切换到RUNNING状态 |
| | | // 否则切换到MSERROR状态 |
| | | int nRet; |
| | | CEquipment* pEq[6] = { pEFEM, pBonder1, pBonder2, pBakeCooling, |
| | | pVacuumBake, pMeasurement}; |
| | | BOOL bIomcOk[7] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE}; |
| | | std::vector<std::promise<void>> promises(6); |
| | | std::vector<std::future<void>> futures; |
| | | |
| | | nRet = pEq[0]->indexerOperationModeChange(IDNEXER_OPERATION_MODE::Start, |
| | | [&](int writeCode, int retCode) -> void { |
| | | bIomcOk[0] = retCode == (int)RET::OK; |
| | | promises[0].set_value(); |
| | | TRACE("a0001\n", writeCode, retCode); |
| | | }); |
| | | if (nRet != 0) { |
| | | LOGI("<Master>EFEM切换Start状态失败"); |
| | | m_strLastError = "EFEM切换Start状态失败."; |
| | | goto WAIT; |
| | | } |
| | | futures.push_back(promises[0].get_future()); |
| | | |
| | | nRet = pEq[1]->indexerOperationModeChange(IDNEXER_OPERATION_MODE::Start, |
| | | [&](int writeCode, int retCode) -> void { |
| | | bIomcOk[1] = retCode == (int)RET::OK; |
| | | promises[1].set_value(); |
| | | TRACE("a0002\n"); |
| | | }); |
| | | if (nRet != 0) { |
| | | LOGI("<Master>Bonder1切换Start状态失败"); |
| | | m_strLastError = "Bonder1切换Start状态失败."; |
| | | goto WAIT; |
| | | } |
| | | futures.push_back(promises[1].get_future()); |
| | | |
| | | nRet = pEq[2]->indexerOperationModeChange(IDNEXER_OPERATION_MODE::Start, |
| | | [&](int writeCode, int retCode) -> void { |
| | | bIomcOk[2] = retCode == (int)RET::OK; |
| | | promises[2].set_value(); |
| | | TRACE("a0003\n"); |
| | | }); |
| | | if (nRet != 0) { |
| | | LOGI("<Master>Bonder2切换Start状态失败"); |
| | | m_strLastError = "Bonder2切换Start状态失败."; |
| | | goto WAIT; |
| | | } |
| | | futures.push_back(promises[2].get_future()); |
| | | |
| | | nRet = pEq[3]->indexerOperationModeChange(IDNEXER_OPERATION_MODE::Start, |
| | | [&](int writeCode, int retCode) -> void { |
| | | bIomcOk[3] = retCode == (int)RET::OK; |
| | | promises[3].set_value(); |
| | | TRACE("a0004\n"); |
| | | }); |
| | | if (nRet != 0) { |
| | | LOGI("<Master>BakeCooling切换Start状态失败"); |
| | | m_strLastError = "BakeCooling切换Start状态失败."; |
| | | goto WAIT; |
| | | } |
| | | futures.push_back(promises[3].get_future()); |
| | | |
| | | nRet = pEq[4]->indexerOperationModeChange(IDNEXER_OPERATION_MODE::Start, |
| | | [&](int writeCode, int retCode) -> void { |
| | | bIomcOk[4] = retCode == (int)RET::OK; |
| | | promises[4].set_value(); |
| | | TRACE("a0005\n"); |
| | | }); |
| | | if (nRet != 0) { |
| | | LOGI("<Master>VacuumBake切换Start状态失败"); |
| | | m_strLastError = "VacuumBake切换Start状态失败."; |
| | | goto WAIT; |
| | | } |
| | | futures.push_back(promises[4].get_future()); |
| | | |
| | | nRet = pEq[5]->indexerOperationModeChange(IDNEXER_OPERATION_MODE::Start, |
| | | [&](int writeCode, int retCode) -> void { |
| | | bIomcOk[5] = retCode == (int)RET::OK; |
| | | promises[5].set_value(); |
| | | TRACE("a0006\n"); |
| | | }); |
| | | if (nRet != 0) { |
| | | LOGI("<Master>Measurement切换Start状态失败"); |
| | | m_strLastError = "Measurement切换Start状态失败."; |
| | | goto WAIT; |
| | | } |
| | | futures.push_back(promises[5].get_future()); |
| | | |
| | | WAIT: |
| | | for (auto& f : futures) { |
| | | f.wait(); // 阻塞等待对应设备完成 |
| | | } |
| | | for (int i = 0; i < 6; i++) { |
| | | if (!bIomcOk[i]) { |
| | | bIomcOk[6] = FALSE; |
| | | LOGI("<Master>%s切换Start状态失败", pEq[i]->getName().c_str()); |
| | | } |
| | | } |
| | | |
| | | // 检查看是否都已经切换到START状态 |
| | | if (!bIomcOk[6]) { |
| | | unlock(); |
| | | setState(MASTERSTATE::MSERROR); |
| | | continue; |
| | | } |
| | | |
| | | |
| | | unlock(); |
| | | Sleep(1000); |
| | | setState(MASTERSTATE::RUNNING); |
| | | continue; |
| | | } |
| | |
| | | |
| | | // 调度逻辑处理 |
| | | else if (m_state == MASTERSTATE::RUNNING) { |
| | | unlock(); |
| | | // LOGI("调度处理中..."); |
| | | // 检测判断robot状态 |
| | | RMDATA& rmd = pEFEM->getRobotMonitoringData(); |
| | | if (rmd.status != ROBOT_STATUS::Idle && rmd.status != ROBOT_STATUS::Run) { |
| | | unlock(); |
| | | continue; |
| | | } |
| | | |
| | | lock(); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | unlock(); |
| | | // 检测到当前有正在下午的任务,确保当前任务完成或中止后继续 |
| | |
| | | } |
| | | |
| | | |
| | | |
| | | // BakeCooling内部 |
| | | // Bake -> Cooling |
| | | m_pActiveRobotTask = createTransferTask_bake_to_cooling(pBakeCooling); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | std::string strDescription = m_pActiveRobotTask->getDescription(); |
| | | unlock(); |
| | | if (m_listener.onRobotTaskEvent != nullptr) { |
| | | m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_CREATE); |
| | | } |
| | | LOGI("创建新任务<%s>...", strDescription.c_str()); |
| | | continue; |
| | | } |
| | | |
| | | |
| | | // Bonder -> BakeCooling |
| | | m_pActiveRobotTask = createTransferTask_bonder_to_bakecooling(pBonder1, pBakeCooling); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | std::string strDescription = m_pActiveRobotTask->getDescription(); |
| | | unlock(); |
| | | if (m_listener.onRobotTaskEvent != nullptr) { |
| | | m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_CREATE); |
| | | } |
| | | LOGI("创建新任务<%s>...", strDescription.c_str()); |
| | | continue; |
| | | } |
| | | |
| | | m_pActiveRobotTask = createTransferTask_bonder_to_bakecooling(pBonder2, pBakeCooling); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | std::string strDescription = m_pActiveRobotTask->getDescription(); |
| | | unlock(); |
| | | if (m_listener.onRobotTaskEvent != nullptr) { |
| | | m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_CREATE); |
| | | } |
| | | LOGI("创建新任务<%s>...", strDescription.c_str()); |
| | | continue; |
| | | } |
| | | |
| | | // Aligner -> Bonder |
| | | m_pActiveRobotTask = createTransferTask(pAligner, pBonder1, primaryType, secondaryType); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | std::string strDescription = m_pActiveRobotTask->getDescription(); |
| | | unlock(); |
| | | if (m_listener.onRobotTaskEvent != nullptr) { |
| | | m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_CREATE); |
| | | } |
| | | LOGI("创建新任务<%s>...", strDescription.c_str()); |
| | | continue; |
| | | } |
| | | |
| | | m_pActiveRobotTask = createTransferTask(pAligner, pBonder2, primaryType, secondaryType); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | std::string strDescription = m_pActiveRobotTask->getDescription(); |
| | | unlock(); |
| | | if (m_listener.onRobotTaskEvent != nullptr) { |
| | | m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_CREATE); |
| | | } |
| | | LOGI("创建新任务<%s>...", strDescription.c_str()); |
| | | continue; |
| | | } |
| | | |
| | | |
| | | // Fliper(G2) -> Aligner |
| | | // VacuumBake(G1) -> Aligner |
| | | m_pActiveRobotTask = createTransferTask(pFliper, pAligner, primaryType, secondaryType); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | std::string strDescription = m_pActiveRobotTask->getDescription(); |
| | | unlock(); |
| | | if (m_listener.onRobotTaskEvent != nullptr) { |
| | | m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_CREATE); |
| | | } |
| | | LOGI("创建新任务<%s>...", strDescription.c_str()); |
| | | continue; |
| | | } |
| | | |
| | | m_pActiveRobotTask = createTransferTask(pVacuumBack, pAligner, primaryType, secondaryType); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | std::string strDescription = m_pActiveRobotTask->getDescription(); |
| | | unlock(); |
| | | if (m_listener.onRobotTaskEvent != nullptr) { |
| | | m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_CREATE); |
| | | } |
| | | LOGI("创建新任务<%s>...", strDescription.c_str()); |
| | | continue; |
| | | } |
| | | |
| | | |
| | | // LoadPort -> Fliper(G2) |
| | | // LoadPort -> VacuumBake(G1) |
| | | CEquipment* pEqTar1 = pVacuumBack; |
| | | CEquipment* pEqTar2 = pFliper; |
| | | // Measurement -> LoadPort |
| | | LOGI("Arm1 %s, Arm2 %s.", rmd.armState[0] ? _T("不可用") : _T("可用"), |
| | | rmd.armState[1] ? _T("不可用") : _T("可用")); |
| | | CLoadPort* pEqLoadPort[] = { pLoadPort1, pLoadPort2, pLoadPort3, pLoadPort4 }; |
| | | CEquipment* pEqTar[] = { pVacuumBake, pFliper }; |
| | | if (primaryType == MaterialsType::G2) { |
| | | pEqTar1 = pFliper; |
| | | pEqTar2 = pVacuumBack; |
| | | pEqTar[0] = pFliper; |
| | | pEqTar[1] = pVacuumBake; |
| | | } |
| | | m_pActiveRobotTask = createTransferTask(pLoadPort1, pEqTar1, primaryType, secondaryType); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | std::string strDescription = m_pActiveRobotTask->getDescription(); |
| | | unlock(); |
| | | if (m_listener.onRobotTaskEvent != nullptr) { |
| | | m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_CREATE); |
| | | for (int s = 0; s < 4; s++) { |
| | | if (!rmd.armState[0] && pEqLoadPort[s]->isEnable() |
| | | && pEqLoadPort[s]->getPortType() == PortType::Unloading |
| | | && pEqLoadPort[s]->getPortMode() == PortMode::ReadyToUnload) { |
| | | m_pActiveRobotTask = createTransferTask(pMeasurement, pEqLoadPort[s], primaryType, secondaryType); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | goto PORT_PUT; |
| | | } |
| | | } |
| | | LOGI("创建新任务<%s>...", strDescription.c_str()); |
| | | continue; |
| | | } |
| | | |
| | | m_pActiveRobotTask = createTransferTask(pLoadPort2, pEqTar1, primaryType, secondaryType); |
| | | PORT_PUT: |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | std::string strDescription = m_pActiveRobotTask->getDescription(); |
| | | unlock(); |
| | | if (m_listener.onRobotTaskEvent != nullptr) { |
| | | m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_CREATE); |
| | | } |
| | | LOGI("创建新任务<%s>...", strDescription.c_str()); |
| | | continue; |
| | | } |
| | | |
| | | |
| | | |
| | | // LoadPort -> VacuumBake(G1) |
| | | m_pActiveRobotTask = createTransferTask(pLoadPort1, pEqTar2, primaryType, secondaryType); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | std::string strDescription = m_pActiveRobotTask->getDescription(); |
| | | unlock(); |
| | | if (m_listener.onRobotTaskEvent != nullptr) { |
| | | m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_CREATE); |
| | | } |
| | | LOGI("创建新任务<%s>...", strDescription.c_str()); |
| | | continue; |
| | | } |
| | | |
| | | m_pActiveRobotTask = createTransferTask(pLoadPort2, pEqTar2, primaryType, secondaryType); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_pActiveRobotTask->pick(); |
| | | std::string strDescription = m_pActiveRobotTask->getDescription(); |
| | | unlock(); |
| | | if (m_listener.onRobotTaskEvent != nullptr) { |
| | |
| | | |
| | | |
| | | // BakeCooling ->Measurement |
| | | if (!rmd.armState[0]) { |
| | | m_pActiveRobotTask = createTransferTask_bakecooling_to_measurement(pBakeCooling, pMeasurement); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_pActiveRobotTask->pick(); |
| | | std::string strDescription = m_pActiveRobotTask->getDescription(); |
| | | unlock(); |
| | | if (m_listener.onRobotTaskEvent != nullptr) { |
| | | m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_CREATE); |
| | | } |
| | | LOGI("创建新任务<%s>...", strDescription.c_str()); |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | |
| | | // Measurement -> LoadPort |
| | | |
| | | // BakeCooling内部 |
| | | // Bake -> Cooling |
| | | if (!rmd.armState[0]) { |
| | | m_pActiveRobotTask = createTransferTask_bake_to_cooling(pBakeCooling); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_pActiveRobotTask->pick(); |
| | | std::string strDescription = m_pActiveRobotTask->getDescription(); |
| | | unlock(); |
| | | if (m_listener.onRobotTaskEvent != nullptr) { |
| | | m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_CREATE); |
| | | } |
| | | LOGI("创建新任务<%s>...", strDescription.c_str()); |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | |
| | | // Bonder -> BakeCooling |
| | | if (!rmd.armState[0]) { |
| | | m_pActiveRobotTask = createTransferTask_bonder_to_bakecooling(pBonder1, pBakeCooling); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_pActiveRobotTask->pick(); |
| | | std::string strDescription = m_pActiveRobotTask->getDescription(); |
| | | unlock(); |
| | | if (m_listener.onRobotTaskEvent != nullptr) { |
| | | m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_CREATE); |
| | | } |
| | | LOGI("创建新任务<%s>...", strDescription.c_str()); |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | if (!rmd.armState[0]) { |
| | | m_pActiveRobotTask = createTransferTask_bonder_to_bakecooling(pBonder2, pBakeCooling); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_pActiveRobotTask->pick(); |
| | | std::string strDescription = m_pActiveRobotTask->getDescription(); |
| | | unlock(); |
| | | if (m_listener.onRobotTaskEvent != nullptr) { |
| | | m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_CREATE); |
| | | } |
| | | LOGI("创建新任务<%s>...", strDescription.c_str()); |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | |
| | | // Fliper(G2) -> Bonder |
| | | // VacuumBake(G1) -> Bonder |
| | | if (!rmd.armState[1] && !pBonder1->hasBondClass()) { |
| | | m_pActiveRobotTask = createTransferTask(pFliper, pBonder1, primaryType, secondaryType, 2); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_pActiveRobotTask->pick(); |
| | | std::string strDescription = m_pActiveRobotTask->getDescription(); |
| | | unlock(); |
| | | if (m_listener.onRobotTaskEvent != nullptr) { |
| | | m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_CREATE); |
| | | } |
| | | LOGI("创建新任务<%s>...", strDescription.c_str()); |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | if (!rmd.armState[1] && !pBonder2->hasBondClass()) { |
| | | m_pActiveRobotTask = createTransferTask(pFliper, pBonder2, primaryType, secondaryType, 2); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_pActiveRobotTask->pick(); |
| | | std::string strDescription = m_pActiveRobotTask->getDescription(); |
| | | unlock(); |
| | | if (m_listener.onRobotTaskEvent != nullptr) { |
| | | m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_CREATE); |
| | | } |
| | | LOGI("创建新任务<%s>...", strDescription.c_str()); |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | if (!rmd.armState[0] && !pBonder1->hasBondClass()) { |
| | | m_pActiveRobotTask = createTransferTask(pVacuumBake, pBonder1, primaryType, secondaryType); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_pActiveRobotTask->pick(); |
| | | std::string strDescription = m_pActiveRobotTask->getDescription(); |
| | | unlock(); |
| | | if (m_listener.onRobotTaskEvent != nullptr) { |
| | | m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_CREATE); |
| | | } |
| | | LOGI("创建新任务<%s>...", strDescription.c_str()); |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | if (!rmd.armState[0] && !pBonder2->hasBondClass()) { |
| | | m_pActiveRobotTask = createTransferTask(pVacuumBake, pBonder2, primaryType, secondaryType); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_pActiveRobotTask->pick(); |
| | | std::string strDescription = m_pActiveRobotTask->getDescription(); |
| | | unlock(); |
| | | if (m_listener.onRobotTaskEvent != nullptr) { |
| | | m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_CREATE); |
| | | } |
| | | LOGI("创建新任务<%s>...", strDescription.c_str()); |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | |
| | | // Aligner -> Fliper(G2) |
| | | // Aligner -> VacuumBake(G1) |
| | | if (!rmd.armState[1]) { |
| | | m_pActiveRobotTask = createTransferTask(pAligner, pFliper, primaryType, secondaryType, 2); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_pActiveRobotTask->pick(); |
| | | std::string strDescription = m_pActiveRobotTask->getDescription(); |
| | | unlock(); |
| | | if (m_listener.onRobotTaskEvent != nullptr) { |
| | | m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_CREATE); |
| | | } |
| | | LOGI("创建新任务<%s>...", strDescription.c_str()); |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | if (!rmd.armState[0]) { |
| | | m_pActiveRobotTask = createTransferTask(pAligner, pVacuumBake, primaryType, secondaryType); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_pActiveRobotTask->pick(); |
| | | std::string strDescription = m_pActiveRobotTask->getDescription(); |
| | | unlock(); |
| | | if (m_listener.onRobotTaskEvent != nullptr) { |
| | | m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_CREATE); |
| | | } |
| | | LOGI("创建新任务<%s>...", strDescription.c_str()); |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | // LoadPort -> Aligner |
| | | for (int s = 0; s < 4; s++) { |
| | | if (!rmd.armState[0] && pEqLoadPort[s]->isEnable() |
| | | && pEqLoadPort[s]->getPortType() == PortType::Loading |
| | | && pEqLoadPort[s]->getPortMode() == PortMode::ReadyToLoad) { |
| | | m_pActiveRobotTask = createTransferTask(pEqLoadPort[s], pAligner, primaryType, secondaryType); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | goto PORT_GET; |
| | | } |
| | | } |
| | | } |
| | | |
| | | PORT_GET: |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_pActiveRobotTask->pick(); |
| | | std::string strDescription = m_pActiveRobotTask->getDescription(); |
| | | unlock(); |
| | | if (m_listener.onRobotTaskEvent != nullptr) { |
| | | m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_CREATE); |
| | | } |
| | | LOGI("创建新任务<%s>...", strDescription.c_str()); |
| | | continue; |
| | | } |
| | | |
| | | unlock(); |
| | | |
| | |
| | | |
| | | // 读标志位 |
| | | for (auto item : m_listEquipment) { |
| | | if (item->getID() == EQ_ID_Bonder1 || |
| | | item->getID() == EQ_ID_Bonder2) { |
| | | const StationIdentifier& station = item->getStation(); |
| | | MemoryBlock& block = item->getReadBitBlock(); |
| | | const StationIdentifier& station = item->getStation(); |
| | | MemoryBlock& block = item->getReadBitBlock(); |
| | | |
| | | int nRet = m_cclink.ReadData2(station, (DeviceType)block.type, |
| | | block.start, block.size, block.buffer); |
| | | if (0 == nRet) { |
| | | item->onReceiveLBData(block.buffer, block.size); |
| | | } |
| | | int nRet = m_cclink.ReadData2(station, (DeviceType)block.type, |
| | | block.start, block.size, block.buffer); |
| | | if (0 == nRet) { |
| | | item->onReceiveLBData(block.buffer, block.size); |
| | | } |
| | | } |
| | | } |
| | |
| | | if (m_pActiveRobotTask->getSrcPosition() == p->getID()) { |
| | | CGlass* pGlass = p->getGlassFromSlot(m_pActiveRobotTask->getSrcSlot()); |
| | | if (pGlass != nullptr) { |
| | | CJobDataB* pJobDataBSrc = pGlass->getJobDataB(); |
| | | if (pJobDataBSrc != nullptr |
| | | && pJobDataBSrc->getCassetteSequenceNo() == pJobDataB->getCassetteSequenceNo() |
| | | && pJobDataBSrc->getJobSequenceNo() == pJobDataB->getJobSequenceNo()) { |
| | | CJobDataS* pJobDataS = pGlass->getJobDataS(); |
| | | if (pJobDataS != nullptr |
| | | && pJobDataS->getCassetteSequenceNo() == pJobDataB->getCassetteSequenceNo() |
| | | && pJobDataS->getJobSequenceNo() == pJobDataB->getJobSequenceNo()) { |
| | | bOk = TRUE; |
| | | LOGI("<CMaster>onPreFethedOutJob, 已校验数据一致性."); |
| | | } |
| | |
| | | BOOL bOk = FALSE; |
| | | lock(); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | if (m_pActiveRobotTask->getTarPosition() == p->getID()) { |
| | | // 是否已经进入手臂(即取片完成),进入下一步,放片 |
| | | if (m_pActiveRobotTask->isPicking() && |
| | | ((m_pActiveRobotTask->getArmNo() == 1 && p->getID() == EQ_ID_ARM_TRAY1) |
| | | || (m_pActiveRobotTask->getArmNo() == 2 && p->getID() == EQ_ID_ARM_TRAY2)) |
| | | ) { |
| | | slot = 1; |
| | | bOk = TRUE; |
| | | } |
| | | |
| | | // 是否放片完成 |
| | | else if (m_pActiveRobotTask->isPlacing() && |
| | | m_pActiveRobotTask->getTarPosition() == p->getID()) { |
| | | CGlass* pGlass = p->getGlassFromSlot(m_pActiveRobotTask->getTarSlot()); |
| | | if (pGlass == nullptr) { |
| | | bOk = TRUE; |
| | | slot = m_pActiveRobotTask->getTarSlot(); |
| | | LOGI("<CMaster>onPreFethedOutJob, 已校验数据一致性."); |
| | | } |
| | | } |
| | | else if (p->getID() == EQ_ID_ARM_TRAY1 || p->getID() == EQ_ID_ARM_TRAY2) { |
| | | slot = 1; |
| | | bOk = TRUE; |
| | | } |
| | | } |
| | | unlock(); |
| | |
| | | if (code == EDCC_FETCHOUT_JOB) { |
| | | lock(); |
| | | if (m_pActiveRobotTask != nullptr && m_pActiveRobotTask->getSrcPosition() == p->getID()) { |
| | | m_pActiveRobotTask->fetchOut(); |
| | | LOGI("开始取片..."); |
| | | } |
| | | unlock(); |
| | | } |
| | | else if (code == EDCC_STORED_JOB) { |
| | | lock(); |
| | | if (m_pActiveRobotTask != nullptr && m_pActiveRobotTask->getTarPosition() == p->getID()) { |
| | | if (m_pActiveRobotTask != nullptr |
| | | && m_pActiveRobotTask->isPicking() |
| | | && ((m_pActiveRobotTask->getArmNo() == 1 && p->getID() == EQ_ID_ARM_TRAY1) |
| | | || (m_pActiveRobotTask->getArmNo() == 2 && p->getID() == EQ_ID_ARM_TRAY2)) |
| | | ) { |
| | | LOGI("取片完成."); |
| | | m_pActiveRobotTask->fetchOut(); |
| | | m_pActiveRobotTask->place(); |
| | | } |
| | | |
| | | else if (m_pActiveRobotTask != nullptr |
| | | && m_pActiveRobotTask->isPlacing() |
| | | && m_pActiveRobotTask->getTarPosition() == p->getID()) { |
| | | m_pActiveRobotTask->stored(); |
| | | m_pActiveRobotTask->completed(); |
| | | LOGI("放片完成..."); |
| | | |
| | | // 完成此条搬送任务,但要把数据和消息上抛应用层 |
| | | unlock(); |
| | | |
| | | |
| | | |
| | | lock(); |
| | |
| | | unlock(); |
| | | } |
| | | }; |
| | | |
| | | listener.onProcessStateChanged = [&](void* pEquipment, PROCESS_STATE state) -> void { |
| | | LOGI("<Master>onProcessStateChanged<%d>", (int)state); |
| | | }; |
| | | pEquipment->setListener(listener); |
| | | pEquipment->setCcLink(&m_cclink); |
| | | m_listEquipment.push_back(pEquipment); |
| | |
| | | pEquipment->setBaseAlarmId(BASE_ALARM_EFEM); |
| | | pEquipment->setName("VacuumBake(G1)"); |
| | | pEquipment->setDescription("VacuumBake(G1)."); |
| | | pEquipment->setReadBitBlock(0x4000, 0x45ff); |
| | | pEquipment->setReadBitBlock(0x5c00, 0x66ff); |
| | | pEquipment->setStation(0, 255); |
| | | addToEquipmentList(pEquipment); |
| | | |
| | |
| | | pEquipment->setBaseAlarmId(BASE_ALARM_EFEM); |
| | | pEquipment->setName("BakeCooling"); |
| | | pEquipment->setDescription("BakeCooling."); |
| | | pEquipment->setReadBitBlock(0x4000, 0x45ff); |
| | | pEquipment->setReadBitBlock(0x5100, 0x5bff); |
| | | pEquipment->setStation(0, 255); |
| | | addToEquipmentList(pEquipment); |
| | | |
| | |
| | | CBakeCooling* pBakeCooling = (CBakeCooling*)getEquipment(EQ_ID_BAKE_COOLING); |
| | | CMeasurement* pMeasurement = (CMeasurement*)getEquipment(EQ_ID_MEASUREMENT); |
| | | |
| | | nRet = pLoadPort1->getPin("Out1")->connectPin(pFliper->getPin("In1")); |
| | | nRet = pLoadPort1->getPin("Out")->connectPin(pAligner->getPin("In1")); |
| | | if (nRet < 0) { |
| | | LOGE("连接LoadPort1-Fliper失败"); |
| | | } |
| | | nRet = pLoadPort2->getPin("Out1")->connectPin(pFliper->getPin("In2")); |
| | | nRet = pLoadPort2->getPin("Out")->connectPin(pAligner->getPin("In2")); |
| | | if (nRet < 0) { |
| | | LOGE("连接LoadPort1-Fliper失败"); |
| | | } |
| | | |
| | | nRet = pLoadPort1->getPin("Out2")->connectPin(pVacuumBake->getPin("In1")); |
| | | nRet = pAligner->getPin("Out1")->connectPin(pFliper->getPin("In")); |
| | | if (nRet < 0) { |
| | | LOGE("连接LoadPort1-VacuumBake失败"); |
| | | LOGE("连接Aligner-Fliper失败"); |
| | | } |
| | | nRet = pLoadPort2->getPin("Out2")->connectPin(pVacuumBake->getPin("In2")); |
| | | nRet = pAligner->getPin("Out2")->connectPin(pVacuumBake->getPin("In")); |
| | | if (nRet < 0) { |
| | | LOGE("连接LoadPort1-VacuumBake失败"); |
| | | LOGE("连接Aligner-VacuumBake失败"); |
| | | } |
| | | |
| | | nRet = pFliper->getPin("Out")->connectPin(pAligner->getPin("In1")); |
| | | nRet = pFliper->getPin("Out1")->connectPin(pBonder1->getPin("In1")); |
| | | if (nRet < 0) { |
| | | LOGE("连接Fliper-Aligner失败"); |
| | | LOGE("连接Fliper-Bonder1失败"); |
| | | } |
| | | nRet = pFliper->getPin("Out2")->connectPin(pBonder2->getPin("In1")); |
| | | if (nRet < 0) { |
| | | LOGE("连接Fliper-Bonder2失败"); |
| | | } |
| | | |
| | | nRet = pVacuumBake->getPin("Out")->connectPin(pAligner->getPin("In2")); |
| | | nRet = pVacuumBake->getPin("Out1")->connectPin(pBonder1->getPin("In2")); |
| | | if (nRet < 0) { |
| | | LOGE("连接VacuumBake-Aligner失败"); |
| | | LOGE("连接VacuumBake-Bonder1失败"); |
| | | } |
| | | |
| | | nRet = pAligner->getPin("Out1")->connectPin(pBonder1->getPin("In")); |
| | | nRet = pVacuumBake->getPin("Out2")->connectPin(pBonder2->getPin("In2")); |
| | | if (nRet < 0) { |
| | | LOGE("连接Aligner-Bondere1失败"); |
| | | } |
| | | |
| | | nRet = pAligner->getPin("Out2")->connectPin(pBonder2->getPin("In")); |
| | | if (nRet < 0) { |
| | | LOGE("连接Aligner-Bondere2失败"); |
| | | LOGE("连接VacuumBake-Bonder2失败"); |
| | | } |
| | | |
| | | nRet = pBonder1->getPin("Out")->connectPin(pBakeCooling->getPin("In1")); |
| | |
| | | |
| | | static int taskSeqNo = 0; |
| | | CRobotTask* CMaster::createTransferTask(CEquipment* pSrcEq, CEquipment* pTarEq, |
| | | MaterialsType primaryType/* = MaterialsType::G1*/, MaterialsType secondaryType/* = MaterialsType::G2*/) |
| | | MaterialsType primaryType/* = MaterialsType::G1*/, MaterialsType secondaryType/* = MaterialsType::G2*/, |
| | | int armNo/* = 1*/) |
| | | { |
| | | CRobotTask* pTask = nullptr; |
| | | CSlot* pSrcSlot, * pTarSlot; |
| | |
| | | if (pSrcSlot != nullptr && nullptr != pTarSlot) { |
| | | pTask = new CRobotTask(); |
| | | pTask->setContext(pSrcSlot->getContext()); |
| | | pTask->setRobotTransferParam(++taskSeqNo, 1, pSrcSlot->getPosition(), |
| | | pTask->setEFEM((CEFEM*)getEquipment(EQ_ID_EFEM)); |
| | | taskSeqNo = pTask->setRobotTransferParam(taskSeqNo, armNo, pSrcSlot->getPosition(), |
| | | pTarSlot->getPosition(), pSrcSlot->getNo(), pTarSlot->getNo()); |
| | | } |
| | | |
| | |
| | | if (pSrcSlot != nullptr && nullptr != pTarSlot) { |
| | | pTask = new CRobotTask(); |
| | | pTask->setContext(pSrcSlot->getContext()); |
| | | pTask->setRobotTransferParam(++taskSeqNo, 1, pSrcSlot->getPosition(), |
| | | pTask->setEFEM((CEFEM*)getEquipment(EQ_ID_EFEM)); |
| | | taskSeqNo = pTask->setRobotTransferParam(taskSeqNo, 1, pSrcSlot->getPosition(), |
| | | pTarSlot->getPosition(), pSrcSlot->getNo(), pTarSlot->getNo()); |
| | | } |
| | | |
| | |
| | | if (pSrcSlot != nullptr && nullptr != pTarSlot) { |
| | | pTask = new CRobotTask(); |
| | | pTask->setContext(pSrcSlot->getContext()); |
| | | pTask->setRobotTransferParam(++taskSeqNo, 1, pSrcSlot->getPosition(), |
| | | pTask->setEFEM((CEFEM*)getEquipment(EQ_ID_EFEM)); |
| | | taskSeqNo = pTask->setRobotTransferParam(taskSeqNo, 1, pSrcSlot->getPosition(), |
| | | pTarSlot->getPosition(), pSrcSlot->getNo(), pTarSlot->getNo()); |
| | | } |
| | | |
| | | |
| | | return pTask; |
| | | } |
| | | |
| | | CRobotTask* CMaster::createTransferTask_bakecooling_to_measurement(CEquipment* pSrcEq, CEquipment* pTarEq) |
| | | { |
| | | std::vector<int> slots = { 3, 4 }; |
| | | |
| | | CRobotTask* pTask = nullptr; |
| | | CSlot* pSrcSlot, * pTarSlot; |
| | | pTarSlot = pTarEq->getAvailableSlotForGlass(MaterialsType::G1); |
| | | pSrcSlot = pSrcEq->getProcessedSlot2(MaterialsType::G1, slots); |
| | | |
| | | if (pSrcSlot != nullptr && nullptr != pTarSlot) { |
| | | pTask = new CRobotTask(); |
| | | pTask->setContext(pSrcSlot->getContext()); |
| | | pTask->setEFEM((CEFEM*)getEquipment(EQ_ID_EFEM)); |
| | | taskSeqNo = pTask->setRobotTransferParam(taskSeqNo, 1, pSrcSlot->getPosition(), |
| | | pTarSlot->getPosition(), pSrcSlot->getNo(), pTarSlot->getNo()); |
| | | } |
| | | |
| | | |
| | | return pTask; |
| | | } |
| | | |
| | | int CMaster::abortCurrentTask() |
| | | { |
| | | lock(); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | m_pActiveRobotTask->abort(); |
| | | } |
| | | unlock(); |
| | | |
| | | if (m_listener.onRobotTaskEvent != nullptr) { |
| | | m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_ABORT); |
| | | } |
| | | |
| | | lock(); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | delete m_pActiveRobotTask; |
| | | m_pActiveRobotTask = nullptr; |
| | | } |
| | | unlock(); |
| | | |
| | | // 当前任务手动中止后,停止调度,需要操作员在解决问题后,重新启动 |
| | | stop(); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | void CMaster::setPortType(unsigned int index, BOOL enable, int type, int mode, |
| | | int cassetteType, int transferMode, BOOL autoChangeEnable) |
| | | { |
| | | ASSERT(index < 4); |
| | | int eqid[] = { EQ_ID_LOADPORT1, EQ_ID_LOADPORT2, EQ_ID_LOADPORT3, EQ_ID_LOADPORT4}; |
| | | CLoadPort* pPort = (CLoadPort*)getEquipment(eqid[index]); |
| | | pPort->localEanblePort(enable); |
| | | pPort->localSetPortType((SERVO::PortType)type); |
| | | pPort->localSetPortMode((SERVO::PortMode)mode); |
| | | pPort->localSetCessetteType((SERVO::CassetteType)cassetteType); |
| | | pPort->localSetTransferMode((SERVO::TransferMode)transferMode); |
| | | pPort->localAutoChangeEnable(autoChangeEnable); |
| | | } |
| | | } |