From dba7d2725cefc162ef58a53bb12b4656434c8bc0 Mon Sep 17 00:00:00 2001
From: LAPTOP-SNT8I5JK\Boounion <Chenluhua@qq.com>
Date: 星期一, 30 六月 2025 08:42:17 +0800
Subject: [PATCH] 1.调试后更新优化;
---
SourceCode/Bond/Servo/CMaster.cpp | 1424 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 1,384 insertions(+), 40 deletions(-)
diff --git a/SourceCode/Bond/Servo/CMaster.cpp b/SourceCode/Bond/Servo/CMaster.cpp
index 2bbfe86..cba74ae 100644
--- a/SourceCode/Bond/Servo/CMaster.cpp
+++ b/SourceCode/Bond/Servo/CMaster.cpp
@@ -1,9 +1,31 @@
#include "stdafx.h"
#include "Common.h"
#include "CMaster.h"
+#include <future>
+#include <vector>
+
namespace SERVO {
CMaster* g_pMaster = NULL;
+
+ unsigned __stdcall DispatchThreadFunction(LPVOID lpParam)
+ {
+ if (g_pMaster != NULL) {
+ return g_pMaster->DispatchProc();
+ }
+
+ return 0;
+ }
+
+ unsigned __stdcall ReadBitsThreadFunction(LPVOID lpParam)
+ {
+ if (g_pMaster != NULL) {
+ return g_pMaster->ReadBitsProc();
+ }
+
+ return 0;
+ }
+
void CALLBACK MasterTimerProc(HWND hWnd, UINT nMsg, UINT nTimerid, DWORD dwTime)
{
if (g_pMaster != NULL) {
@@ -13,21 +35,63 @@
CMaster::CMaster()
{
- m_listener = {nullptr, nullptr};
+ m_listener = {};
+ m_bDataModify = FALSE;
+ m_hEventReadBitsThreadExit[0] = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+ m_hEventReadBitsThreadExit[1] = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+ m_hReadBitsThreadHandle = nullptr;
+ m_nReadBitsThreadAddr = 0;
+ m_hDispatchEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+ m_hEventDispatchThreadExit[0] = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+ m_hEventDispatchThreadExit[1] = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+ m_hDispatchThreadHandle = nullptr;
+ m_nDispatchThreadAddr = 0;
+ m_ullStartTime = 0;
+ m_ullRunTime = 0;
+ m_state = MASTERSTATE::READY;
+ m_pActiveRobotTask = nullptr;
+ m_nLastError = 0;
+ InitializeCriticalSection(&m_criticalSection);
}
CMaster::~CMaster()
{
- for (auto item : m_listEquipment) {
- delete item;
+ if (m_hEventReadBitsThreadExit[0] != nullptr) {
+ ::CloseHandle(m_hEventReadBitsThreadExit[0]);
+ m_hEventReadBitsThreadExit[0] = nullptr;
}
- m_listEquipment.clear();
+
+ if (m_hEventReadBitsThreadExit[1] != nullptr) {
+ ::CloseHandle(m_hEventReadBitsThreadExit[1]);
+ m_hEventReadBitsThreadExit[1] = nullptr;
+ }
+
+ if (m_hDispatchEvent != nullptr) {
+ ::CloseHandle(m_hDispatchEvent);
+ m_hDispatchEvent = nullptr;
+ }
+
+ if (m_hEventDispatchThreadExit[0] != nullptr) {
+ ::CloseHandle(m_hEventDispatchThreadExit[0]);
+ m_hEventDispatchThreadExit[0] = nullptr;
+ }
+
+ if (m_hEventDispatchThreadExit[1] != nullptr) {
+ ::CloseHandle(m_hEventDispatchThreadExit[1]);
+ m_hEventDispatchThreadExit[1] = nullptr;
+ }
+
+ DeleteCriticalSection(&m_criticalSection);
}
void CMaster::setListener(MasterListener listener)
{
- m_listener.onEqAlive = listener.onEqAlive;
- m_listener.onEqCimStateChanged = listener.onEqCimStateChanged;
+ m_listener = listener;
+ }
+
+ CRobotTask* CMaster::getActiveRobotTask()
+ {
+ return m_pActiveRobotTask;
}
int CMaster::init()
@@ -62,33 +126,87 @@
// 初始化添加各子设备
- {
- CEFEM* pEquipment = new CEFEM();
- pEquipment->setID(EQ_ID_EFEM);
- pEquipment->setName("EFEM(ROBOT)");
- pEquipment->setDescription("EFEM(ROBOT).");
- pEquipment->setReadBitBlock(0x4000, 0x45ff);
- pEquipment->setStation(0, 255);
- addEquipment(pEquipment);
+ CLoadPort* pPort1, * pPort2, * pPort3, * pPort4;
+ CBonder* pBonder1, * pBonder2;
+ CEFEM* pEfem;
+ CArm* pArm;
+ CArmTray* pArmTray1, * pArmTray2;
+ CFliper* pFliper;
+ CVacuumBake* pVacuumBake;
+ CAligner* pAligner;
+ CBakeCooling* pBakeCooling;
+ CMeasurement* pMeasurement;
- pEquipment->init();
- LOGE("已添加“EFEM(ROBOT)”.");
- }
- /*
- {
- CBonder* pBonder = new CBonder();
- pBonder->setName("Bonder 1");
- pBonder->setDescription("Bonder 1.");
- pBonder->setReadBitBlock(0x4600, 0x4bff);
- pBonder->setStation(1, 3);
- addEquipment(pBonder);
- LOGE("已添加“Bonder 1”.");
- }
- */
+ pPort1 = addLoadPort(0);
+ pPort2 = addLoadPort(1);
+ pPort3 = addLoadPort(2);
+ pPort4 = addLoadPort(3);
+ pEfem = addEFEM();
+ pArm = addArm();
+ pArmTray1 = addArmTray(0);
+ pArmTray2 = addArmTray(1);
+ pFliper = addFliper();
+ pVacuumBake = addVacuumBake();
+ pAligner = addAligner();
+ pBonder1 = addBonder(0);
+ pBonder2 = addBonder(1);
+ pBakeCooling = addBakeCooling();
+ pMeasurement = addMeasurement();
+
+ ASSERT(pEfem);
+ ASSERT(pFliper);
+ ASSERT(pVacuumBake);
+ ASSERT(pAligner);
+ ASSERT(pBonder1);
+ ASSERT(pBonder2);
+ ASSERT(pBakeCooling);
+ ASSERT(pMeasurement);
+
+ pEfem->setPort(0, pPort1);
+ pEfem->setPort(1, pPort2);
+ pEfem->setPort(2, pPort3);
+ pEfem->setPort(3, pPort4);
+ pEfem->setFliper(pFliper);
+ pEfem->setAligner(pAligner);
+ pEfem->setArmTray(0, pArmTray1);
+ pEfem->setArmTray(1, pArmTray2);
+ pPort1->setArm(pArm);
+ pPort2->setArm(pArm);
+ pPort3->setArm(pArm);
+ pPort4->setArm(pArm);
+ pArmTray1->setArm(pArm);
+ pArmTray2->setArm(pArm);
+ pFliper->setArm(pArm);
+ pVacuumBake->setArm(pArm);
+ pAligner->setArm(pArm);
+ pBonder1->setArm(pArm);
+ pBonder2->setArm(pArm);
+ pBakeCooling->setArm(pArm);
+ pMeasurement->setArm(pArm);
+
+ connectEquipments();
+
+
+
+
+
+ // 读缓存数据
+ readCache();
+
// 定时器
g_pMaster = this;
SetTimer(NULL, 1, 250, (TIMERPROC)MasterTimerProc);
+
+
+ // 调度线程
+ m_hDispatchThreadHandle = (HANDLE)_beginthreadex(NULL, 0, SERVO::DispatchThreadFunction, this,
+ 0, &m_nDispatchThreadAddr);
+
+
+ // 监控bit线程
+ m_hReadBitsThreadHandle = (HANDLE)_beginthreadex(NULL, 0, SERVO::ReadBitsThreadFunction, this,
+ 0, &m_nReadBitsThreadAddr);
LOGI("<Master>初始化完成.");
@@ -97,15 +215,589 @@
int CMaster::term()
{
+ SetEvent(m_hEventReadBitsThreadExit[0]);
+ SetEvent(m_hEventDispatchThreadExit[0]);
+ ::WaitForSingleObject(m_hEventReadBitsThreadExit[1], INFINITE);
+ ::WaitForSingleObject(m_hEventDispatchThreadExit[1], INFINITE);
+
LOGI("<Master>正在结束程序.");
for (auto item : m_listEquipment) {
item->term();
}
+ saveCache();
+
+ lock();
+ if (m_pActiveRobotTask != nullptr) {
+ delete m_pActiveRobotTask;
+ m_pActiveRobotTask = nullptr;
+ }
+ unlock();
+
+ for (auto item : m_listEquipment) {
+ delete item;
+ }
+ m_listEquipment.clear();
+
return 0;
}
- int CMaster::addEquipment(CEquipment* pEquipment)
+ int CMaster::start()
+ {
+ if (m_state != MASTERSTATE::READY) {
+ return -1;
+ }
+
+ setState(MASTERSTATE::STARTING);
+ m_ullStartTime = GetTickCount64();
+
+ return 0;
+ }
+
+ int CMaster::stop()
+ {
+ // 运行时间为累加结果,本次停止时刷新;
+ if (m_state != MASTERSTATE::RUNNING) {
+ return -1;
+ }
+
+ m_ullRunTime += (GetTickCount64() - m_ullStartTime);
+ setState(MASTERSTATE::STOPPING);
+
+ return 0;
+ }
+
+ void CMaster::clearError()
+ {
+ m_nLastError = 0;
+ m_strLastError = "";
+ setState(MASTERSTATE::READY);
+ }
+
+ ULONGLONG CMaster::getRunTime()
+ {
+ if (m_state == MASTERSTATE::RUNNING)
+ return m_ullRunTime + (GetTickCount64() - m_ullStartTime);
+ else
+ return m_ullRunTime;
+ }
+
+ MASTERSTATE CMaster::getState()
+ {
+ return m_state;
+ }
+
+ unsigned CMaster::DispatchProc()
+ {
+ // 优先考虑的类型和次要类型
+ // 一种情况,如果不分主次,一直搬G1, 等到Bonder1和Bonder2都放了G1, Aligner也放了G1,
+ // Bonder1和Bonder2需要的G2就过不来了
+ // 最基本的实现,可以G2和G2轮流搬送,但最好根据Bonder的需求来决定
+ MaterialsType primaryType, secondaryType;
+
+
+ // 各种机器
+ 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* 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(pVacuumBake);
+ ASSERT(pAligner);
+ ASSERT(pBonder1);
+ ASSERT(pBonder2);
+ ASSERT(pBakeCooling);
+ ASSERT(pMeasurement);
+
+ while (1) {
+ // 待退出信号或时间到
+ HANDLE hEvents[] = { m_hEventDispatchThreadExit[0], m_hDispatchEvent };
+ int nRet = WaitForMultipleObjects(2, hEvents, FALSE, 1000);
+ if (nRet == WAIT_OBJECT_0) {
+ break;
+ }
+
+
+ // 如果状态为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, TRUE, TRUE, TRUE, TRUE, TRUE, 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();
+ setState(MASTERSTATE::RUNNING);
+ continue;
+ }
+
+
+ // 处理完成当前事务后,切换到停止或就绪状态
+ else if (m_state == MASTERSTATE::STOPPING) {
+ unlock();
+ LOGI("<Master>开始切换各设备到 Stop 模式...");
+
+ std::vector<std::promise<void>> promises(6);
+ std::vector<std::future<void>> futures;
+ BOOL bIomcOk[7] = { FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE };
+
+ int nRet;
+ CEquipment* pEq[6] = { pEFEM, pBonder1, pBonder2, pBakeCooling,
+ pVacuumBake, pMeasurement };
+
+ for (int i = 0; i < 1; ++i) {
+ nRet = pEq[i]->indexerOperationModeChange(IDNEXER_OPERATION_MODE::Stop,
+ [i, &promises, &bIomcOk](int writeCode, int retCode) -> void {
+ bIomcOk[i] = retCode == (int)RET::OK;
+ promises[i].set_value();
+ TRACE("s000%d: ret=%d\n", i + 1, retCode);
+ });
+ if (nRet != 0) {
+ LOGI("<Master>%s切换Stop状态发送失败", pEq[i]->getName().c_str());
+ m_strLastError = pEq[i]->getName() + "切换Stop状态发送失败.";
+ bIomcOk[i] = FALSE;
+ promises[i].set_value(); // 避免 wait 阻塞
+ }
+ futures.push_back(promises[i].get_future());
+ }
+
+ for (auto& f : futures) {
+ f.wait(); // 等待所有完成
+ }
+
+ for (int i = 0; i < 6; ++i) {
+ if (!bIomcOk[i]) {
+ bIomcOk[6] = FALSE;
+ LOGI("<Master>%s切换Stop状态失败", pEq[i]->getName().c_str());
+ }
+ }
+
+ if (!bIomcOk[6]) {
+ setState(MASTERSTATE::MSERROR);
+ continue;
+ }
+
+ LOGI("<Master>所有设备成功切换到 Stop 模式");
+ setState(MASTERSTATE::READY);
+ continue;
+ }
+
+
+ // 调度逻辑处理
+ else if (m_state == MASTERSTATE::RUNNING) {
+ // 检测判断robot状态
+ RMDATA& rmd = pEFEM->getRobotMonitoringData();
+ if (rmd.status != ROBOT_STATUS::Idle && rmd.status != ROBOT_STATUS::Run) {
+ unlock();
+ continue;
+ }
+
+ if (m_pActiveRobotTask != nullptr) {
+ if (m_pActiveRobotTask->isPicked()) {
+ m_pActiveRobotTask->place();
+ }
+ unlock();
+ // 检测到当前有正在下午的任务,确保当前任务完成或中止后继续
+ // LOGI("检测到当前有正在下午的任务,确保当前任务完成或中止后继续...");
+ continue;
+ }
+
+
+ // 此处检测优先类型和次要类型(G1或G2)
+ // 如果其中一Bonder有单个玻璃,优先取它的配对类型,否则无所谓了
+ primaryType = MaterialsType::G1;
+ secondaryType = MaterialsType::G2;
+ if ((!pBonder1->canPlaceGlassInSlot(0) && !pBonder1->canPlaceGlassInSlot(1))
+ && (!pBonder2->canPlaceGlassInSlot(0) && !pBonder2->canPlaceGlassInSlot(1))) {
+ // 如果G1和G2都满了,那就看Aligner, 如果Aligner有玻璃为G1, 则取G2
+ CGlass* pGlass = pAligner->getGlassFromSlot(1);
+ if (pGlass != nullptr && pGlass->getType() == MaterialsType::G1) {
+ primaryType = MaterialsType::G2;
+ secondaryType = MaterialsType::G1;
+ }
+ }
+ else if ((pBonder1->canPlaceGlassInSlot(0) && !pBonder1->canPlaceGlassInSlot(1))
+ || (pBonder2->canPlaceGlassInSlot(0) && !pBonder2->canPlaceGlassInSlot(1))) {
+ primaryType = MaterialsType::G2;
+ secondaryType = MaterialsType::G1;
+ }
+
+
+ // Measurement -> LoadPort
+ if (rmd.armState[0] || rmd.armState[1]) {
+ 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) {
+ pEqTar[0] = pFliper;
+ pEqTar[1] = pVacuumBake;
+ }
+ 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;
+ }
+ }
+ }
+
+ PORT_PUT:
+ 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;
+ }
+
+
+ // 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;
+ }
+ }
+
+
+
+ // 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);
+ 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) {
+ pEFEM->setContext(m_pActiveRobotTask->getContext());
+ 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();
+
+ }
+ unlock();
+ }
+
+ SetEvent(m_hEventDispatchThreadExit[1]);
+
+
+ // _endthreadex(0);
+ TRACE("CMaster::DispatchProc 线程退出\n");
+ return 0;
+ }
+
+ unsigned CMaster::ReadBitsProc()
+ {
+ while (1) {
+ // 待退出信号或时间到
+ int nRet = ::WaitForSingleObject(m_hEventReadBitsThreadExit[0], 1000);
+ if (nRet == WAIT_OBJECT_0) {
+ break;
+ }
+
+ // 读标志位
+ for (auto item : m_listEquipment) {
+ const StationIdentifier& station = item->getStation();
+ MemoryBlock& block = item->getReadBitBlock();
+ if (block.end > block.start) {
+ int nRet = m_cclink.ReadData2(station, (DeviceType)block.type,
+ block.start, block.size, block.buffer);
+ if (0 == nRet) {
+ item->onReceiveLBData(block.buffer, block.size);
+ }
+ }
+ }
+ }
+
+ SetEvent(m_hEventReadBitsThreadExit[1]);
+
+
+ // _endthreadex(0);
+ TRACE("CMaster::ReadBitsProc 线程退出\n");
+ return 0;
+ }
+
+ int CMaster::addToEquipmentList(CEquipment* pEquipment)
{
EquipmentListener listener;
listener.onAlive = [&](void* pEquipment, BOOL bAlive) -> void {
@@ -120,11 +812,179 @@
m_listener.onEqCimStateChanged(this, p, bOn);
}
};
+ listener.onAlarm = [&](void* pEquipment, int state, int alarmId, int unitId, int level) -> void {
+ CEquipment* p = (CEquipment*)pEquipment;
+ if (m_listener.onEqAlarm != nullptr) {
+ m_listener.onEqAlarm(this, p, state, alarmId, unitId, level);
+ }
+ };
+ listener.onVcrEventReport = [&](void* pEquipment, void* pReport) -> void {
+ CEquipment* p = (CEquipment*)pEquipment;
+ CVcrEventReport* p2 = (CVcrEventReport*)pReport;
+ if (m_listener.onEqVcrEventReport != nullptr) {
+ m_listener.onEqVcrEventReport(this, p, p2);
+ }
+ };
+ listener.onPreFethedOutJob = [&](void* pEquipment, int port, CJobDataB* pJobDataB) -> BOOL {
+ CEquipment* p = (CEquipment*)pEquipment;
+
+
+ // 取片,更新当前搬送任务
+ BOOL bOk = FALSE;
+ lock();
+ if (m_pActiveRobotTask != nullptr) {
+ if (m_pActiveRobotTask->getSrcPosition() == p->getID()) {
+ CGlass* pGlass = p->getGlassFromSlot(m_pActiveRobotTask->getSrcSlot());
+ if (pGlass != nullptr) {
+ CJobDataS* pJobDataS = pGlass->getJobDataS();
+ if (pJobDataS != nullptr
+ && pJobDataS->getCassetteSequenceNo() == pJobDataB->getCassetteSequenceNo()
+ && pJobDataS->getJobSequenceNo() == pJobDataB->getJobSequenceNo()) {
+ bOk = TRUE;
+ LOGI("<CMaster>onPreFethedOutJob, 已校验数据一致性.");
+ }
+ }
+ }
+ else if (p->getID() == EQ_ID_ARM_TRAY1 || p->getID() == EQ_ID_ARM_TRAY2) {
+ bOk = TRUE;
+ }
+ }
+ unlock();
+
+ if (!bOk) {
+ LOGE("<CMaster>onPreFethedOutJob, 数据校验失败.");
+ }
+
+ return bOk;
+
+ };
+ listener.onPreStoredJob = [&](void* pEquipment, int port, CJobDataB* pJobDataB, short& slot) -> BOOL {
+ CEquipment* p = (CEquipment*)pEquipment;
+
+
+ // 放片,更新当前搬送任务
+ BOOL bOk = FALSE;
+ lock();
+ if (m_pActiveRobotTask != nullptr) {
+ // 是否已经进入手臂(即取片完成),进入下一步,放片
+ 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 (m_pActiveRobotTask->isRestoring() &&
+ m_pActiveRobotTask->getSrcPosition() == p->getID()) {
+ CGlass* pGlass = p->getGlassFromSlot(m_pActiveRobotTask->getSrcSlot());
+ if (pGlass == nullptr && m_pActiveRobotTask->getSrcSlot() == port) {
+ bOk = TRUE;
+ slot = m_pActiveRobotTask->getSrcSlot();
+ LOGI("<CMaster>onPreFethedOutJob, 已校验数据一致性.");
+ }
+ }
+ }
+ unlock();
+
+ if (!bOk) {
+ LOGE("<CMaster>onPreStoredJob, 数据校验失败.");
+ }
+
+ return bOk;
+
+ };
+ listener.onDataChanged = [&](void* pEquipment, int code) -> void {
+ m_bDataModify = TRUE;
+ CEquipment* p = (CEquipment*)pEquipment;
+ if (m_listener.onEqDataChanged != nullptr) {
+ m_listener.onEqDataChanged(this, p, 0);
+ }
+
+ // 取放片,更新当前搬送任务
+ if (code == EDCC_FETCHOUT_JOB) {
+ lock();
+ if (m_pActiveRobotTask != nullptr && m_pActiveRobotTask->getSrcPosition() == p->getID()) {
+ LOGI("开始取片...");
+ }
+ unlock();
+ }
+ else if (code == EDCC_STORED_JOB) {
+ lock();
+ 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->picked();
+ }
+
+ else if (m_pActiveRobotTask != nullptr
+ && m_pActiveRobotTask->isPlacing()
+ && m_pActiveRobotTask->getTarPosition() == p->getID()) {
+ m_pActiveRobotTask->stored();
+ m_pActiveRobotTask->completed();
+ LOGI("放片完成...");
+ // 完成此条搬送任务,但要把数据和消息上抛应用层
+ unlock();
+
+
+ lock();
+ if (m_listener.onRobotTaskEvent != nullptr) {
+ m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_FINISH);
+ }
+ delete m_pActiveRobotTask;
+ m_pActiveRobotTask = nullptr;
+ }
+
+ else if (m_pActiveRobotTask != nullptr
+ && m_pActiveRobotTask->isRestoring()
+ && m_pActiveRobotTask->getSrcPosition() == p->getID()) {
+ m_pActiveRobotTask->stored();
+ m_pActiveRobotTask->restored();
+ LOGI("回撤完成...");
+ // 完成此条搬送任务,但要把数据和消息上抛应用层
+ unlock();
+
+
+ lock();
+ if (m_listener.onRobotTaskEvent != nullptr) {
+ m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_RESTORE);
+ }
+ delete m_pActiveRobotTask;
+ m_pActiveRobotTask = nullptr;
+ stop();
+ }
+ 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);
return 0;
+ }
+
+ std::list<CEquipment*>& CMaster::getEquipmentList()
+ {
+ return m_listEquipment;
}
CEquipment* CMaster::getEquipment(int id)
@@ -136,6 +996,194 @@
return nullptr;
}
+ /*
+ * 添加LoadPort1
+ * index -- 0~3
+ */
+ CLoadPort* CMaster::addLoadPort(int index)
+ {
+ ASSERT(index == 0 || index == 1 || index == 2 || index == 3);
+
+
+ char szName[64];
+ sprintf_s(szName, 64, "LoadPort %d", index + 1);
+ CLoadPort* pEquipment = new CLoadPort();
+ pEquipment->setIndex(index);
+ pEquipment->setID(EQ_ID_LOADPORT1 + index);
+ pEquipment->setName(szName);
+ pEquipment->setDescription(szName);
+ addToEquipmentList(pEquipment);
+
+
+ pEquipment->init();
+ LOGE("已添加“%s”.", pEquipment->getName().c_str());
+
+
+ return pEquipment;
+ }
+
+ CFliper* CMaster::addFliper()
+ {
+ CFliper* pEquipment = new CFliper();
+ pEquipment->setID(EQ_ID_FLIPER);
+ pEquipment->setBaseAlarmId(BASE_ALARM_EFEM);
+ pEquipment->setName("Fliper(G2)");
+ pEquipment->setDescription("Fliper(G2).");
+ pEquipment->setReadBitBlock(0x0, 0x0);
+ pEquipment->setStation(0, 255);
+ addToEquipmentList(pEquipment);
+
+
+ pEquipment->init();
+ LOGE("已添加“Fliper”.");
+ return pEquipment;
+ }
+
+ CVacuumBake* CMaster::addVacuumBake()
+ {
+ CVacuumBake* pEquipment = new CVacuumBake();
+ pEquipment->setID(EQ_ID_VACUUMBAKE);
+ pEquipment->setBaseAlarmId(BASE_ALARM_EFEM);
+ pEquipment->setName("VacuumBake(G1)");
+ pEquipment->setDescription("VacuumBake(G1).");
+ pEquipment->setReadBitBlock(0x5c00, 0x66ff);
+ pEquipment->setStation(0, 255);
+ addToEquipmentList(pEquipment);
+
+
+ pEquipment->init();
+ LOGE("已添加“VacuumBake”.");
+
+ return pEquipment;
+ }
+
+ CAligner* CMaster::addAligner()
+ {
+ CAligner* pEquipment = new CAligner();
+ pEquipment->setID(EQ_ID_ALIGNER);
+ pEquipment->setBaseAlarmId(BASE_ALARM_EFEM);
+ pEquipment->setName("Aligner");
+ pEquipment->setDescription("Aligner.");
+ pEquipment->setReadBitBlock(0x0, 0x0);
+ pEquipment->setStation(0, 255);
+ addToEquipmentList(pEquipment);
+
+
+ pEquipment->init();
+ LOGE("已添加“Aligner”.");
+
+ return pEquipment;
+ }
+
+ CEFEM* CMaster::addEFEM()
+ {
+ CEFEM* pEquipment = new CEFEM();
+ pEquipment->setID(EQ_ID_EFEM);
+ pEquipment->setBaseAlarmId(BASE_ALARM_EFEM);
+ pEquipment->setName("EFEM(ROBOT)");
+ pEquipment->setDescription("EFEM(ROBOT).");
+ pEquipment->setReadBitBlock(0x3000, 0x3aff);
+ pEquipment->setStation(0, 255);
+ addToEquipmentList(pEquipment);
+
+
+ pEquipment->init();
+ LOGE("已添加“EFEM(ROBOT)”.");
+
+ return pEquipment;
+ }
+
+ CArm* CMaster::addArm()
+ {
+ CArm* pEquipment = new CArm();
+ pEquipment->setID(EQ_ID_ARM);
+ pEquipment->setBaseAlarmId(BASE_ALARM_EFEM);
+ pEquipment->setName("ARM");
+ pEquipment->setDescription("ARM.");
+ addToEquipmentList(pEquipment);
+
+
+ pEquipment->init();
+ LOGE("已添加“ARM”.");
+
+ return pEquipment;
+ }
+
+ CArmTray* CMaster::addArmTray(int index)
+ {
+ CArmTray* pEquipment = new CArmTray();
+ pEquipment->setID(index == 0 ? EQ_ID_ARM_TRAY1 : EQ_ID_ARM_TRAY2);
+ pEquipment->setBaseAlarmId(BASE_ALARM_EFEM);
+ pEquipment->setName(index == 0 ? "Arm Tray1" : "Arm Tray2");
+ pEquipment->setDescription(index == 0 ? "Arm Tray1." : "Arm Tray2.");
+ addToEquipmentList(pEquipment);
+
+
+ pEquipment->init();
+ LOGE("已添加“%s”.", pEquipment->getName().c_str());
+
+ return pEquipment;
+ }
+
+ /* 添加bonder1 或 bonder2
+ * index -- 0, bonder1
+ * index -- 1, bonder2
+ */
+ CBonder* CMaster::addBonder(int index)
+ {
+ ASSERT(index == 0 || index == 1);
+ CBonder* pEquipment = new CBonder();
+ pEquipment->setID(EQ_ID_Bonder1 + index);
+ pEquipment->setName(index == 0 ? "Bonder 1" : "Bonder 2");
+ pEquipment->setDescription(index == 0 ? "Bonder 1." : "Bonder 2.");
+ pEquipment->setStation(0, 255);
+ pEquipment->setReadBitBlock(index == 0 ? 0x3b00 : 0x4600,
+ index == 0 ? 0x5600 : 0x6100);
+ pEquipment->setIndex(index);
+ addToEquipmentList(pEquipment);
+
+
+ pEquipment->init();
+ LOGE("已添加“%s”.", pEquipment->getName().c_str());
+
+
+ return pEquipment;
+ }
+
+ CBakeCooling* CMaster::addBakeCooling()
+ {
+ CBakeCooling* pEquipment = new CBakeCooling();
+ pEquipment->setID(EQ_ID_BAKE_COOLING);
+ pEquipment->setBaseAlarmId(BASE_ALARM_EFEM);
+ pEquipment->setName("BakeCooling");
+ pEquipment->setDescription("BakeCooling.");
+ pEquipment->setReadBitBlock(0x5100, 0x5bff);
+ pEquipment->setStation(0, 255);
+ addToEquipmentList(pEquipment);
+
+ pEquipment->init();
+ LOGE("已添加“Aligner”.");
+
+ return pEquipment;
+ }
+
+ CMeasurement* CMaster::addMeasurement()
+ {
+ CMeasurement* pEquipment = new CMeasurement();
+ pEquipment->setID(EQ_ID_MEASUREMENT);
+ pEquipment->setBaseAlarmId(BASE_ALARM_EFEM);
+ pEquipment->setName("Measurement");
+ pEquipment->setDescription("Measurement.");
+ pEquipment->setReadBitBlock(0x6700, 0x6e00);
+ pEquipment->setStation(0, 255);
+ addToEquipmentList(pEquipment);
+
+ pEquipment->init();
+ LOGE("已添加“Measurement”.");
+
+ return pEquipment;
+ }
+
void CMaster::onTimer(UINT nTimerid)
{
for (auto item : m_listEquipment) {
@@ -143,21 +1191,317 @@
}
- // 按一定频率扫描LB数据
static int i = 0;
i++;
- if (i % (4 * 1) == 0) {
- for (auto item : m_listEquipment) {
- 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);
- }
+ // 自动保存缓存
+ if (i % (4 * 2) == 0) {
+ if (m_bDataModify) {
+ saveCacheAndBackups();
+ m_bDataModify = FALSE;
}
}
+
+ }
+
+ void CMaster::connectEquipments()
+ {
+ int nRet;
+ 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* 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);
+
+ nRet = pLoadPort1->getPin("Out")->connectPin(pAligner->getPin("In1"));
+ if (nRet < 0) {
+ LOGE("连接LoadPort1-Fliper失败");
+ }
+ nRet = pLoadPort2->getPin("Out")->connectPin(pAligner->getPin("In2"));
+ if (nRet < 0) {
+ LOGE("连接LoadPort1-Fliper失败");
+ }
+
+ nRet = pAligner->getPin("Out1")->connectPin(pFliper->getPin("In"));
+ if (nRet < 0) {
+ LOGE("连接Aligner-Fliper失败");
+ }
+ nRet = pAligner->getPin("Out2")->connectPin(pVacuumBake->getPin("In"));
+ if (nRet < 0) {
+ LOGE("连接Aligner-VacuumBake失败");
+ }
+
+ nRet = pFliper->getPin("Out1")->connectPin(pBonder1->getPin("In1"));
+ if (nRet < 0) {
+ LOGE("连接Fliper-Bonder1失败");
+ }
+ nRet = pFliper->getPin("Out2")->connectPin(pBonder2->getPin("In1"));
+ if (nRet < 0) {
+ LOGE("连接Fliper-Bonder2失败");
+ }
+
+ nRet = pVacuumBake->getPin("Out1")->connectPin(pBonder1->getPin("In2"));
+ if (nRet < 0) {
+ LOGE("连接VacuumBake-Bonder1失败");
+ }
+ nRet = pVacuumBake->getPin("Out2")->connectPin(pBonder2->getPin("In2"));
+ if (nRet < 0) {
+ LOGE("连接VacuumBake-Bonder2失败");
+ }
+
+ nRet = pBonder1->getPin("Out")->connectPin(pBakeCooling->getPin("In1"));
+ if (nRet < 0) {
+ LOGE("连接Bonder1-BakeCooling失败");
+ }
+
+ nRet = pBonder2->getPin("Out")->connectPin(pBakeCooling->getPin("In2"));
+ if (nRet < 0) {
+ LOGE("连接Bonder2-BakeCooling失败");
+ }
+
+ nRet = pBakeCooling->getPin("Out")->connectPin(pMeasurement->getPin("In"));
+ if (nRet < 0) {
+ LOGE("连接BakeCooling-LoadPort3失败");
+ }
+
+ nRet = pMeasurement->getPin("Out1")->connectPin(pLoadPort3->getPin("In"));
+ if (nRet < 0) {
+ LOGE("连接BakeCooling-LoadPort3失败");
+ }
+
+ nRet = pMeasurement->getPin("Out2")->connectPin(pLoadPort4->getPin("In"));
+ if (nRet < 0) {
+ LOGE("连接BakeCooling-LoadPort4失败");
+ }
+ }
+
+ int CMaster::saveCache()
+ {
+ CFile file;
+ if (!file.Open(m_strFilepath.c_str(), CFile::modeCreate | CFile::modeWrite)) {
+ return -1;
+ }
+
+ CArchive ar(&file, CArchive::store);
+ serialize(ar);
+ ar.Close();
+ file.Close();
+
+ return 0;
+ }
+
+ int CMaster::saveCacheAndBackups()
+ {
+ saveCache();
+
+
+ // 创建备份目录
+ CString strNewFile;
+ CString strFileDir = m_strFilepath.c_str();
+ int index = strFileDir.ReverseFind('\\');
+ ASSERT(index > 0);
+ strFileDir = strFileDir.Left(index);
+ strFileDir = strFileDir + _T("Backups");
+ ::CreateDirectory(strFileDir, nullptr);
+
+ CTime time = CTime::GetCurrentTime();
+ strNewFile.Format(_T("%s//Master_%d_%02d_%02d_%02d_%02d_%02d.dat"),
+ (LPTSTR)(LPCTSTR)strFileDir,
+ time.GetYear(), time.GetMonth(), time.GetDay(),
+ time.GetHour(), time.GetMinute(), time.GetSecond());
+ ::CopyFile(m_strFilepath.c_str(), strNewFile, FALSE);
+
+ return 0;
+ }
+
+ void CMaster::setCacheFilepath(const char* pszFilepath)
+ {
+ m_strFilepath = pszFilepath;
+ }
+
+ int CMaster::readCache()
+ {
+ try {
+ CFile file;
+ if (!file.Open(m_strFilepath.c_str(), CFile::modeRead)) {
+ return -1;
+ }
+
+ CArchive ar(&file, CArchive::load);
+ serialize(ar);
+ ar.Close();
+ file.Close();
+ }
+ catch (CFileException* e) {
+ TCHAR szErr[512];
+ e->GetErrorMessage(szErr, 512);
+ AfxMessageBox(szErr);
+ e->Delete();
+ }
+
+ return 0;
+ }
+
+ void CMaster::serialize(CArchive& ar)
+ {
+ for (auto item : m_listEquipment) {
+ item->serialize(ar);
+ }
+ }
+
+ void CMaster::setState(MASTERSTATE state)
+ {
+ m_state = state;
+ if (m_listener.onMasterStateChanged != nullptr) {
+ m_listener.onMasterStateChanged(this, m_state);
+ }
+ }
+
+ static int taskSeqNo = 0;
+ CRobotTask* CMaster::createTransferTask(CEquipment* pSrcEq, CEquipment* pTarEq,
+ MaterialsType primaryType/* = MaterialsType::G1*/, MaterialsType secondaryType/* = MaterialsType::G2*/,
+ int armNo/* = 1*/)
+ {
+ CRobotTask* pTask = nullptr;
+ CSlot* pSrcSlot, * pTarSlot;
+ pTarSlot = pTarEq->getAvailableSlotForGlass(primaryType);
+ pSrcSlot = pSrcEq->getProcessedSlot(primaryType);
+ if (pSrcSlot == nullptr || nullptr == pTarSlot) {
+ pTarSlot = pTarEq->getAvailableSlotForGlass(secondaryType);
+ pSrcSlot = pSrcEq->getProcessedSlot(secondaryType);
+ }
+
+
+ if (pSrcSlot != nullptr && nullptr != pTarSlot) {
+ pTask = new CRobotTask();
+ pTask->setContext(pSrcSlot->getContext());
+ pTask->setEFEM((CEFEM*)getEquipment(EQ_ID_EFEM));
+ taskSeqNo = pTask->setRobotTransferParam(taskSeqNo, armNo, pSrcSlot->getPosition(),
+ pTarSlot->getPosition(), pSrcSlot->getNo(), pTarSlot->getNo());
+ }
+
+
+ return pTask;
+ }
+
+ CRobotTask* CMaster::createTransferTask_bonder_to_bakecooling(CEquipment* pSrcEq, CEquipment* pTarEq)
+ {
+ std::vector<int> slots = {1, 3};
+
+ CRobotTask* pTask = nullptr;
+ CSlot* pSrcSlot, * pTarSlot;
+ pTarSlot = pTarEq->getAvailableSlotForGlass2(MaterialsType::G1, slots);
+ pSrcSlot = pSrcEq->getProcessedSlot(MaterialsType::G1);
+
+ 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;
+ }
+
+ CRobotTask* CMaster::createTransferTask_bake_to_cooling(CEquipment* pSrcEq)
+ {
+ std::vector<int> slotsTar = { 2, 4 };
+ std::vector<int> slotsSrc = { 1, 3 };
+
+ CRobotTask* pTask = nullptr;
+ CSlot* pSrcSlot, * pTarSlot;
+ pTarSlot = pSrcEq->getAvailableSlotForGlass2(MaterialsType::G1, slotsTar);
+ pSrcSlot = pSrcEq->getProcessedSlot2(MaterialsType::G1, slotsSrc);
+
+ 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;
+ }
+
+ CRobotTask* CMaster::createTransferTask_bakecooling_to_measurement(CEquipment* pSrcEq, CEquipment* pTarEq)
+ {
+ std::vector<int> slots = { 2, 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;
+ }
+
+ int CMaster::restoreCurrentTask()
+ {
+ lock();
+ if (m_pActiveRobotTask != nullptr) {
+ m_pActiveRobotTask->restore();
+ }
+ unlock();
+
+
+ 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);
}
}
--
Gitblit v1.9.3