| | |
| | | bool CControlJobManagerDlg::m_bHasState = false; |
| | | CControlJobManagerDlg::State CControlJobManagerDlg::m_state{}; |
| | | |
| | | namespace { |
| | | constexpr int kPortCount = 4; |
| | | constexpr int kSlotCount = 8; |
| | | constexpr int kMatG1 = 1; |
| | | constexpr int kMatG2 = 2; |
| | | |
| | | int NormalizeWarpMaterial(int material) |
| | | { |
| | | return (material == kMatG2) ? kMatG2 : kMatG1; |
| | | } |
| | | |
| | | void EnsureWarpDefaults(PJWarp& warp) |
| | | { |
| | | bool hasSelectedPort = false; |
| | | for (int p = 0; p < kPortCount; ++p) { |
| | | if (warp.selectedPorts[p]) { |
| | | hasSelectedPort = true; |
| | | } |
| | | for (int s = 0; s < kSlotCount; ++s) { |
| | | warp.materialSlots[p][s] = NormalizeWarpMaterial(warp.materialSlots[p][s]); |
| | | } |
| | | } |
| | | |
| | | for (int s = 0; s < kSlotCount; ++s) { |
| | | warp.material[s] = NormalizeWarpMaterial(warp.material[s]); |
| | | } |
| | | |
| | | if (!hasSelectedPort && 0 <= warp.port && warp.port < kPortCount) { |
| | | warp.selectedPorts[warp.port] = TRUE; |
| | | for (int s = 0; s < kSlotCount; ++s) { |
| | | warp.checkSlots[warp.port][s] = warp.checkSlot[s]; |
| | | warp.materialSlots[warp.port][s] = NormalizeWarpMaterial(warp.material[s]); |
| | | } |
| | | } |
| | | |
| | | int firstSelectedPort = -1; |
| | | for (int p = 0; p < kPortCount; ++p) { |
| | | if (warp.selectedPorts[p]) { |
| | | firstSelectedPort = p; |
| | | break; |
| | | } |
| | | } |
| | | warp.port = firstSelectedPort; |
| | | |
| | | if (firstSelectedPort >= 0) { |
| | | for (int s = 0; s < kSlotCount; ++s) { |
| | | warp.checkSlot[s] = warp.checkSlots[firstSelectedPort][s]; |
| | | warp.material[s] = NormalizeWarpMaterial(warp.materialSlots[firstSelectedPort][s]); |
| | | } |
| | | } |
| | | else { |
| | | for (int s = 0; s < kSlotCount; ++s) { |
| | | warp.checkSlot[s] = FALSE; |
| | | warp.material[s] = kMatG1; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // CControlJobManagerDlg 对话框 |
| | | |
| | | IMPLEMENT_DYNAMIC(CControlJobManagerDlg, CDialogEx) |
| | |
| | | PJWarp pjWarp = {}; |
| | | pjWarp.pj = pj; |
| | | pjWarp.port = -1; |
| | | for (int s = 0; s < kSlotCount; ++s) { |
| | | pjWarp.material[s] = kMatG1; |
| | | } |
| | | for (int p = 0; p < kPortCount; ++p) { |
| | | pjWarp.selectedPorts[p] = FALSE; |
| | | for (int s = 0; s < kSlotCount; ++s) { |
| | | pjWarp.checkSlots[p][s] = FALSE; |
| | | pjWarp.materialSlots[p][s] = kMatG1; |
| | | } |
| | | } |
| | | m_pjWarps.push_back(pjWarp); |
| | | } |
| | | } |
| | |
| | | return; |
| | | } |
| | | |
| | | |
| | | // 先应用 |
| | | for (int i = 0; i < 3; i++) { |
| | | if (m_pages[i]->IsWindowVisible()) { |
| | |
| | | } |
| | | GetDlgItem(IDC_BUTTON_APPLY)->EnableWindow(FALSE); |
| | | |
| | | |
| | | // 先检查数据正确性 |
| | | int checkCount = 0; |
| | | for (auto item : m_pjWarps) { |
| | | for (auto& item : m_pjWarps) { |
| | | EnsureWarpDefaults(item); |
| | | if (!item.addToCj) continue; |
| | | checkCount++; |
| | | } |
| | |
| | | AfxMessageBox(_T("您没有选择要进行工艺处理的Process Job!\n请在要进行工艺处理的Process Job前打勾。")); |
| | | return; |
| | | } |
| | | |
| | | |
| | | SERVO::CLoadPort* pPorts[4]; |
| | | pPorts[0] = (SERVO::CLoadPort*)master.getEquipment(EQ_ID_LOADPORT1); |
| | |
| | | |
| | | bool bProcessStart[] = {false, false, false, false}; |
| | | std::vector<SERVO::CProcessJob*> pjs; |
| | | for (auto item : m_pjWarps) { |
| | | for (auto& item : m_pjWarps) { |
| | | EnsureWarpDefaults(item); |
| | | if (!item.addToCj) continue; |
| | | if (item.port == -1) continue; |
| | | BOOL bCheck = FALSE; |
| | | for (int i = 0; i < 8; i++) { |
| | | if (item.checkSlot[i]) { |
| | | bCheck = TRUE; |
| | | |
| | | bool hasAnyCheckedSlot = false; |
| | | for (int p = 0; p < kPortCount; ++p) { |
| | | if (!item.selectedPorts[p]) continue; |
| | | for (int s = 0; s < kSlotCount; ++s) { |
| | | if (item.checkSlots[p][s]) { |
| | | hasAnyCheckedSlot = true; |
| | | break; |
| | | } |
| | | } |
| | | if (!bCheck) continue; |
| | | if (hasAnyCheckedSlot) break; |
| | | } |
| | | if (!hasAnyCheckedSlot) continue; |
| | | |
| | | SERVO::CProcessJob* pScr = (SERVO::CProcessJob*)item.pj; |
| | | pScr->setPjWarp(item); |
| | |
| | | pj->setRecipe(SERVO::RecipeMethod::NoTuning, pScr->recipeSpec()); |
| | | |
| | | std::vector<SERVO::CarrierSlotInfo> carriers; |
| | | for (int p = 0; p < kPortCount; ++p) { |
| | | if (!item.selectedPorts[p] || pPorts[p] == nullptr) { |
| | | continue; |
| | | } |
| | | |
| | | SERVO::CarrierSlotInfo csi; |
| | | csi.carrierId = pPorts[item.port]->getCassetteId(); |
| | | for (int i = 0; i < 8; i++) { |
| | | if (item.checkSlot[i]) { |
| | | SERVO::CGlass* pGlass = pPorts[item.port]->getGlassFromSlot(i+1); |
| | | csi.carrierId = pPorts[p]->getCassetteId(); |
| | | for (int s = 0; s < kSlotCount; ++s) { |
| | | if (!item.checkSlots[p][s]) continue; |
| | | SERVO::CGlass* pGlass = pPorts[p]->getGlassFromSlot(s + 1); |
| | | if (pGlass != nullptr) { |
| | | csi.slots.push_back(i + 1); |
| | | csi.slots.push_back(s + 1); |
| | | } |
| | | } |
| | | } |
| | | if (!csi.slots.empty()) { |
| | | carriers.push_back(csi); |
| | | bProcessStart[p] = true; |
| | | } |
| | | } |
| | | |
| | | if (carriers.empty()) { |
| | | delete pj; |
| | | continue; |
| | | } |
| | | |
| | | pj->setCarriers(carriers); |
| | | pjs.push_back(pj); |
| | | bProcessStart[item.port] = true; |
| | | |
| | | m_pControlJob->addPJ(pScr->id()); |
| | | } |
| | | |
| | | |
| | | if (pjs.empty()) { |
| | | AfxMessageBox(_T("没有需要进行工艺处理的Process Job!\n可能未选择Port或选择任何物料。")); |
| | |
| | | return; |
| | | } |
| | | |
| | | // 成功后同步到 slot 的 glass |
| | | for (auto& warp : m_pjWarps) { |
| | | EnsureWarpDefaults(warp); |
| | | if (!warp.addToCj) continue; |
| | | |
| | | // 成功,要判断,同步到slot的glass中,类型等 |
| | | for (int p = 0; p < 4; p++) { |
| | | if (m_pjWarps[p].port == -1) continue; |
| | | ASSERT(0 <= m_pjWarps[p].port && m_pjWarps[p].port <= 3); |
| | | SERVO::CProcessJob* pj = (SERVO::CProcessJob*)warp.pj; |
| | | int nRecipeID = RecipeManager::getInstance().getIdByPPID(pj->recipeSpec()); |
| | | RecipeInfo stRecipeInfo = RecipeManager::getInstance().getRecipeByPPID(pj->recipeSpec()); |
| | | std::vector<DeviceRecipe> vecRecipeInfo = stRecipeInfo.vecDeviceList; |
| | | |
| | | SERVO::CLoadPort* pLoadPort = pPorts[m_pjWarps[p].port]; |
| | | for (int i = 0; i < SLOT_MAX; ++i) { |
| | | SERVO::CSlot* pSlot = pLoadPort->getSlot(i); |
| | | for (int p = 0; p < kPortCount; ++p) { |
| | | if (!warp.selectedPorts[p]) continue; |
| | | SERVO::CLoadPort* pLoadPort = pPorts[p]; |
| | | if (pLoadPort == nullptr) continue; |
| | | |
| | | for (int s = 0; s < SLOT_MAX; ++s) { |
| | | SERVO::CSlot* pSlot = pLoadPort->getSlot(s); |
| | | if (!pSlot) continue; |
| | | |
| | | SERVO::CGlass* pGlass = dynamic_cast<SERVO::CGlass*>(pSlot->getContext()); |
| | |
| | | SERVO::CJobDataS* pJobDataS = pGlass->getJobDataS(); |
| | | if (pJobDataS == nullptr) continue; |
| | | |
| | | |
| | | // 设置 Panel ID 和勾选框 |
| | | SERVO::CProcessJob* pj = (SERVO::CProcessJob*)m_pjWarps[p].pj; |
| | | int nRecipeID = RecipeManager::getInstance().getIdByPPID(pj->recipeSpec()); |
| | | RecipeInfo stRecipeInfo = RecipeManager::getInstance().getRecipeByPPID(pj->recipeSpec()); |
| | | std::vector<DeviceRecipe> vecRecipeInfo = stRecipeInfo.vecDeviceList; |
| | | |
| | | pGlass->setScheduledForProcessing(m_pjWarps[p].checkSlot[i]); |
| | | pGlass->setType(static_cast<SERVO::MaterialsType>(m_pjWarps[p].material[i])); |
| | | const BOOL checked = (s < kSlotCount) ? warp.checkSlots[p][s] : FALSE; |
| | | const int mat = (s < kSlotCount) ? NormalizeWarpMaterial(warp.materialSlots[p][s]) : kMatG1; |
| | | pGlass->setScheduledForProcessing(checked); |
| | | pGlass->setType(static_cast<SERVO::MaterialsType>(mat)); |
| | | |
| | | pJobDataS->setLotId(pj->getLotId().c_str()); |
| | | pJobDataS->setProductId(pj->getProductId().c_str()); |
| | | pJobDataS->setOperationId(pj->getOperationId().c_str()); |
| | | pJobDataS->setMaterialsType(m_pjWarps[p].material[i]); |
| | | pJobDataS->setMaterialsType(mat); |
| | | pJobDataS->setMasterRecipe(nRecipeID); |
| | | |
| | | for (const auto& info : vecRecipeInfo) { |
| | | const std::string& name = info.strDeviceName; |
| | | short nRecipeID = (short)info.nRecipeID; |
| | | |
| | | short nDeviceRecipeID = (short)info.nRecipeID; |
| | | if (name == EQ_NAME_EFEM) { |
| | | pJobDataS->setDeviceRecipeId(0, nRecipeID); |
| | | pJobDataS->setDeviceRecipeId(0, nDeviceRecipeID); |
| | | } |
| | | else if (name == EQ_NAME_BONDER1) { |
| | | pJobDataS->setDeviceRecipeId(1, nRecipeID); |
| | | pJobDataS->setDeviceRecipeId(1, nDeviceRecipeID); |
| | | } |
| | | else if (name == EQ_NAME_BONDER2) { |
| | | pJobDataS->setDeviceRecipeId(2, nRecipeID); |
| | | pJobDataS->setDeviceRecipeId(2, nDeviceRecipeID); |
| | | } |
| | | else if (name == EQ_NAME_BAKE_COOLING) { |
| | | pJobDataS->setDeviceRecipeId(3, nRecipeID); |
| | | pJobDataS->setDeviceRecipeId(3, nDeviceRecipeID); |
| | | } |
| | | else if (name == EQ_NAME_VACUUMBAKE) { |
| | | pJobDataS->setDeviceRecipeId(4, nRecipeID); |
| | | pJobDataS->setDeviceRecipeId(4, nDeviceRecipeID); |
| | | } |
| | | else if (name == EQ_NAME_MEASUREMENT) { |
| | | pJobDataS->setDeviceRecipeId(5, nRecipeID); |
| | | pJobDataS->setDeviceRecipeId(5, nDeviceRecipeID); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // process start |
| | | for (int p = 0; p < 4; p++) { |
| | | if (bProcessStart[p]) { |
| | | for (int p = 0; p < kPortCount; p++) { |
| | | if (!bProcessStart[p]) continue; |
| | | if (pPorts[p] == nullptr) continue; |
| | | |
| | | short jobExistence[12] = { 0 }; |
| | | short slotProcess = 0; |
| | | const short scanMap = pPorts[p]->getScanCassetteMap(); |
| | |
| | | Sleep(100); |
| | | } |
| | | } |
| | | } |
| | | |