// CCOS.Dev.GEN.SPELLMAN.cpp : 定义 DLL 应用程序的导出函数。 // #include "stdafx.h" #include #include using namespace std::placeholders; //#include "logger.temp.h" #include "CCOS.Dev.Generator.SPELLMAN.h" #include "Helper.JSON.hpp" using namespace CCOS::Dev::Detail::Generator; namespace nsGEN = CCOS::Dev::Detail::Generator; #pragma warning (disable:4244) // warning C4244: “初始化”: 从“double”转换到“float”,可能丢失数据 #pragma warning (disable:4305) // warning C4305: “参数”: 从“double”到“float”截断 #pragma warning (disable:4267) // warning C4267 : “初始化”: 从“size_t”转换到“int”,可能丢失数据 static const int msTimeOut_Lock = 500; #ifdef _WIN64 #ifdef _DEBUG static const auto COM_SCFDllName = "Ccos.Dev.SerialSCFX64D.dll"; #else static const auto COM_SCFDllName = "Ccos.Dev.SerialSCFX64.dll"; #endif #endif #ifdef _WIN64 #ifdef _DEBUG static const auto TCP_SCFDllName = "Ccos.Dev.TcpipSCFX64D.dll"; #else static const auto TCP_SCFDllName = "Ccos.Dev.TcpipSCFX64.dll"; #endif #endif //----------------------------------------------------------------------------- // SPELLMANDevice //----------------------------------------------------------------------------- float g_MA_List[] = { 8, 10, 12.5, 16, 20, 25, 32, 40, 50, 64, 80, 100, 125, 160, 200, 250, 320, 400, 500, 640 }; float g_MAS_List[] = { 1, 1.25, 1.6, 2, 2.5, 3.2, 4, 5, 6.4, 8, 10, 12.5, 16, 20, 25, 32, 40, 50, 64, 80, 100, 125, 160, 200, 250, 320, 400, 500, 640, 800, 1000 }; float g_MS_List[] = { 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 25, 32, 40, 50, 64, 80, 100, 125, 160, 200, 250, 320, 400, 500, 640, 800, 1000, 1250, 1600, 2000, 2500, 3200, 4000, 5000, 6400, 8000, 10000 }; int g_AECFIELD_List[] = { 1, 10, 100, 11, 101, 111 }; std::vector gf_MA_List = { 8, 10, 12.5, 16, 20, 25, 32, 40, 50, 64, 80, 100, 125, 160, 200, 250, 320, 400, 500, 640 }; nsGEN::SPELLMANDevice::SPELLMANDevice(std::shared_ptr center, nsSCF::SCF SCF) : super(center, SCF) { assert(EventCenter); //CreateLogger("SPELLMAN"); m_DoseUnit.m_KV.reset(new KVMould(0.0, 40.0, 120.0, 1.0)); m_DoseUnit.m_MA.reset(new MAMould(0.0, 1.0, 1000.0, 0.1)); m_DoseUnit.m_MS.reset(new MSMould(0.0, 1.0, 10000.0, 0.01)); m_DoseUnit.m_MAS.reset(new MASMould(0.0, 0.5, 1000.0, 0.01)); m_DoseUnit.m_Techmode.reset(new TECHMODEMould(0, 0, 2, 1)); m_DoseUnit.m_WS.reset(new WORKSTATIONMould(1, 0, 5, 1)); m_DoseUnit.m_Focus.reset(new FOCUSMould(1, 0, 1, 1)); m_DoseUnit.m_AECField.reset(new AECFIELDMould(0, 0, 111, 1)); m_DoseUnit.m_AECFilm.reset(new AECFILMMould(0, 0, 2, 1)); m_DoseUnit.m_AECDensity.reset(new AECDENSITYMould(0, -4, 4, 1)); m_DoseUnit.m_HE.reset(new TUBEHEATMould(0, 0, 100, 1)); m_DoseUnit.m_PostKV.reset(new POSTKVMould(0.0, 40.0, 120.0, 1.0)); m_DoseUnit.m_PostMA.reset(new POSTMAMould(0.0, 1.0, 1000.0, 0.1)); m_DoseUnit.m_PostMS.reset(new POSTMSMould(0.0, 1.0, 10000.0, 0.01)); m_DoseUnit.m_PostMAS.reset(new POSTMASMould(0.0, 0.5, 1000.0, 0.01)); m_DoseUnit.m_GenSynState.reset(new GENSYNSTATEMould(0, AttrKey::GENERATOR_SYNC_ERR, AttrKey::GENERATOR_SYNC_MAX, 1)); m_DoseUnit.m_GenState.reset(new GENSTATEMould(0, AttrKey::GENERATOR_STATUS_SHUTDOWN, AttrKey::GENERATOR_STATUS_MAX, 1)); m_DoseUnit.m_GenTotalExpNumber.reset(new TOTALEXPNUMMould(0, 0, 9999, 1)); m_DoseUnit.m_GenTotalAcqTimes.reset(new TOTALACQTIMESMould(0, 0, 9999, 1)); m_DoseUnit.m_GenTubeCoolWaitTimes.reset(new TUBECOOLTIMEMould(0, 0, 9999, 1)); m_DoseUnit.m_GenTubeOverLoadNumber.reset(new TUBEOVERLOADNUMMould(0, 0, 9999, 1)); m_DoseUnit.m_GenCurrentExpNumber.reset(new CUREXPNUMMould(0, 0, 9999, 1)); m_DoseUnit.m_ExpMode.reset(new EXPMODEMould(AttrKey::EXPMODE_TYPE::Single)); m_DoseUnit.m_FrameRate.reset(new FRAMERATEMould(0, 0, 16, 1)); m_DoseUnit.m_FLMode.reset(new FLUModeMould(AttrKey::GENERATOR_FLUMode::GENERATOR_FLMODE_NOTFLU)); //m_DoseUnit.m_EXAMMode.reset(new EXAMMODEMould(EXAMMODE_TYPE::MANUAL)); m_MSGUnit.reset(new nsDetail::MSGUnit(center, nsGEN::GeneratorUnitType)); m_DAP.reset(new DevDAP::DOSEMould(0.0, 0.0, 1000.0, 0.01)); m_hGenPostEvent = CreateEvent(NULL, TRUE, FALSE, NULL); m_pHardwareStatusThread = NULL; OnCallBack(); Register(); Reset(); Sleep(500); HWSend("SMK07"); //1 初始化时使能系统配置类型 指令system marker SMKnn 逸动C - ARM系统设置为7. HWSend("DSN01"); //TRODirection /* //以下的设置,需要注意默认值是否正确 HWSend("RSM1"); //立刻发送RSM命令 //表示脚闸的涵义,0 not used , 1 rad , 2 control ,3 cine. HWSend("FLD2"); //doselevel :H M L ,默认是2 HWSend("FFP2"); HWSend("FTO060"); //timeout 60s //XET :SetSyncMode(m_nSyncMode); HWSend("XET1"); //timer : LFC用来设置灯丝最大值,直到收到反馈,结束timer。 */ RefreshData(); StartHardwareStatusThread(); } nsGEN::SPELLMANDevice::~SPELLMANDevice() { CloseHandle(m_hGenPostEvent); } std::string nsGEN::SPELLMANDevice::GetGUID() const { //PRINTA_INFO("\n===============GetGUID : %s ===================\n", GeneratorUnitType); return GeneratorUnitType; } void nsGEN::SPELLMANDevice::Register() { auto Disp = &Dispatch; superGen::Register(Disp); superGen::RegisterRAD(Disp); superGen::RegisterAEC(Disp); superGen::RegisterExpEnable(Disp); superGen::RegisterGeneratortoSyncStatus(Disp); Disp->Get.Push(m_MSGUnit->GetKey().c_str(), [this](std::string& out) { out = m_MSGUnit->JSGet(); return RET_STATUS::RET_SUCCEED; }); auto fun_Clear_DAP = [this](auto a, auto&) { return Clear_DAP(); }; Disp->Action.Push("Clear_DAP", fun_Clear_DAP); auto fun_GetValue_DAP = [this](auto a, auto& b) { float value = 0; RET_STATUS ret = GetValue_DAP(value); b = ToJSON(value); return ret; }; Disp->Action.Push("GetValue_DAP", fun_GetValue_DAP); auto fun_StartMove = [this](auto a,auto& b) { return StartMove(); }; Disp->Action.Push("StartMove", fun_StartMove); auto fun_EndMove = [this](auto a, auto& b) { return EndMove(); }; Disp->Action.Push("EndMove", fun_EndMove); } RET_STATUS nsGEN::SPELLMANDevice::IncKV() { if (m_DoseUnit.m_ExpMode->JSGet() == AttrKey::EXPMODE_TYPE::TOMO) { if (!m_DoseUnit.m_KV->CanInc()) return RET_STATUS::RET_SUCCEED; return HWSend("FLK+"); } else { if (!m_DoseUnit.m_KV->CanInc()) return RET_STATUS::RET_SUCCEED; return HWSend("RKVI"); } } RET_STATUS nsGEN::SPELLMANDevice::DecKV() { if (m_DoseUnit.m_ExpMode->JSGet() == AttrKey::EXPMODE_TYPE::TOMO) { if (!m_DoseUnit.m_KV->CanDec()) return RET_STATUS::RET_SUCCEED; return HWSend("FLK-"); } else { if (!m_DoseUnit.m_KV->CanDec()) return RET_STATUS::RET_SUCCEED; return HWSend("RKVD"); } } RET_STATUS nsGEN::SPELLMANDevice::SetKV(float value) { if (!m_DoseUnit.m_KV->Verify(value)) return RET_STATUS::RET_SUCCEED; if (m_DoseUnit.m_ExpMode->JSGet() != AttrKey::EXPMODE_TYPE::TOMO) { char temp[50] = { 0 }; sprintf_s(temp, "RKV%03d", (int)value); return HWSend(temp); } else { char temp[50] = { 0 }; sprintf_s(temp, "FLK%03d", (int)value); return HWSend(temp); } } RET_STATUS nsGEN::SPELLMANDevice::IncMA() { if (m_DoseUnit.m_ExpMode->JSGet() != AttrKey::EXPMODE_TYPE::TOMO) { if (!m_DoseUnit.m_MA->CanInc()) return RET_STATUS::RET_SUCCEED; if (m_DoseUnit.m_Techmode->Get() == AttrKey::TECHMODE_V2TYPE::ET_MAS) { //PRINTA_INFO("\n Techmode is MAS, can't inc MA"); return RET_STATUS::RET_FAILED; } return HWSend("RMAI"); } else { if (!m_DoseUnit.m_MA->CanInc()) return RET_STATUS::RET_SUCCEED; return HWSend("FLM+"); } } RET_STATUS nsGEN::SPELLMANDevice::DecMA() { if (m_DoseUnit.m_ExpMode->JSGet() != AttrKey::EXPMODE_TYPE::TOMO) { if (!m_DoseUnit.m_MA->CanDec()) return RET_STATUS::RET_SUCCEED; if (m_DoseUnit.m_Techmode->Get() == AttrKey::TECHMODE_V2TYPE::ET_MAS) { //PRINTA_INFO("\n Techmode is MAS, can't dec MA"); return RET_STATUS::RET_FAILED; } return HWSend("RMAD"); } else { if (!m_DoseUnit.m_MA->CanDec()) return RET_STATUS::RET_SUCCEED; return HWSend("FLM-"); } } RET_STATUS nsGEN::SPELLMANDevice::SetMA(float value) { if (!m_DoseUnit.m_MA->Verify(value)) return RET_STATUS::RET_SUCCEED; if (m_DoseUnit.m_Techmode->Get() == AttrKey::TECHMODE_V2TYPE::ET_MAS) { //PRINTA_INFO("\n Techmode is MAS, can't set MA"); return RET_STATUS::RET_FAILED; } if (m_DoseUnit.m_ExpMode->JSGet() != AttrKey::EXPMODE_TYPE::TOMO) { char temp[50] = { 0 }; sprintf_s(temp, "RMA%06d", (int)(value * 100)); return HWSend(temp); } else { char temp[50] = { 0 }; sprintf_s(temp, "FLM%03d", (int)(value * 10)); return HWSend(temp); } } RET_STATUS nsGEN::SPELLMANDevice::IncMS() { if (!m_DoseUnit.m_MS->CanInc()) return RET_STATUS::RET_SUCCEED; if (m_DoseUnit.m_Techmode->Get() == AttrKey::TECHMODE_V2TYPE::ET_MAS) { //PRINTA_INFO("\n Techmode is MAS, can't inc MS"); return RET_STATUS::RET_FAILED; } return HWSend("RMSI"); } RET_STATUS nsGEN::SPELLMANDevice::DecMS() { if (!m_DoseUnit.m_MS->CanDec()) return RET_STATUS::RET_SUCCEED; if (m_DoseUnit.m_Techmode->Get() == AttrKey::TECHMODE_V2TYPE::ET_MAS) { //PRINTA_INFO("\n Techmode is MAS, can't dec MS"); return RET_STATUS::RET_FAILED; } return HWSend("RMSD"); } RET_STATUS nsGEN::SPELLMANDevice::SetMS(float value) { if (!m_DoseUnit.m_MA->Verify(value)) return RET_STATUS::RET_SUCCEED; if (m_DoseUnit.m_Techmode->Get() == AttrKey::TECHMODE_V2TYPE::ET_MAS) { //PRINTA_INFO("\n Techmode is MAS, can't set MS"); return RET_STATUS::RET_FAILED; } char temp[50] { 0 }; //RMS%07d 新协议, RMS%04d 旧协议. sprintf_s(temp, "RMS%07d", (int)(value * 100)); return HWSend(temp); } RET_STATUS nsGEN::SPELLMANDevice::IncMAS() { if (!m_DoseUnit.m_MAS->CanInc()) return RET_STATUS::RET_SUCCEED; if (m_DoseUnit.m_Techmode->Get() != AttrKey::TECHMODE_V2TYPE::ET_MAS) { //PRINTA_INFO("\n Techmode is not MAS, can't inc MAS"); return RET_STATUS::RET_FAILED; } return HWSend("RMXI"); } RET_STATUS nsGEN::SPELLMANDevice::DecMAS() { if (!m_DoseUnit.m_MAS->CanDec()) return RET_STATUS::RET_SUCCEED; if (m_DoseUnit.m_Techmode->Get() != AttrKey::TECHMODE_V2TYPE::ET_MAS) { //PRINTA_INFO("\n Techmode is not MAS, can't dec MAS"); return RET_STATUS::RET_FAILED; } return HWSend("RMXD"); } RET_STATUS nsGEN::SPELLMANDevice::SetMAS(float value) { if (!m_DoseUnit.m_MA->Verify(value)) return RET_STATUS::RET_SUCCEED; if (m_DoseUnit.m_Techmode->Get() != AttrKey::TECHMODE_V2TYPE::ET_MAS) { //PRINTA_INFO("\n Techmode is not MAS, can't set MAS"); return RET_STATUS::RET_FAILED; } char temp[50] = { 0 }; sprintf_s(temp, "RMX%06d", (int)(value * 1000)); return HWSend(temp); } RET_STATUS nsGEN::SPELLMANDevice::SetTechmode(int value) { if (!m_DoseUnit.m_Techmode->Verify(value)) return RET_STATUS::RET_SUCCEED; if (value == AttrKey::TECHMODE_V2TYPE::ET_AEC)//if AEC, translate to time. why? i need reason. value = AttrKey::TECHMODE_V2TYPE::ET_TIME; char temp[50] = { 0 }; sprintf_s(temp, "RET%01d", (int)value); return HWSend(temp); } RET_STATUS nsGEN::SPELLMANDevice::SetFocus(int value) { if (!m_DoseUnit.m_Focus->Verify(value)) return RET_STATUS::RET_SUCCEED; char temp[50] = { 0 }; sprintf_s(temp, "RFO%01d", (int)value); return HWSend(temp); } RET_STATUS nsGEN::SPELLMANDevice::SetAECDensity(int value) { if (!m_DoseUnit.m_AECDensity->Verify(value)) return RET_STATUS::RET_SUCCEED; if (m_DoseUnit.m_Techmode->Get() == AttrKey::TECHMODE_V2TYPE::ET_AEC) return RET_STATUS::RET_FAILED; char temp[50] = { 0 }; if (value >= 0) { sprintf_s(temp, "RFN+%01d", (int)value); } else { sprintf_s(temp, "RFN-%01d", (int)value); } return HWSend(temp); } RET_STATUS nsGEN::SPELLMANDevice::SetAECField(int value) { if (!m_DoseUnit.m_AECField->Verify(value)) return RET_STATUS::RET_SUCCEED; if (m_DoseUnit.m_Techmode->Get() == AttrKey::TECHMODE_V2TYPE::ET_MAS) return RET_STATUS::RET_FAILED; char temp[50] = { 0 }; sprintf_s(temp, "RFI%03d", (int)value); return HWSend(temp); } RET_STATUS nsGEN::SPELLMANDevice::SetAECFilm(int value) { if (!m_DoseUnit.m_AECFilm->Verify(value)) return RET_STATUS::RET_SUCCEED; if (m_DoseUnit.m_Techmode->Get() == AttrKey::TECHMODE_V2TYPE::ET_MAS) return RET_STATUS::RET_FAILED; char temp[50] = { 0 }; sprintf_s(temp, "RFS%03d", (int)value); return HWSend(temp); } RET_STATUS nsGEN::SPELLMANDevice::SetWS(const string value) { int tempws = 0; if (value == "Table") tempws = 0; else if (value == "Wall") tempws = 1; else if (value == "Direct") tempws = 2; else if (value == "Free") tempws = 3; char temp[50] = { 0 }; sprintf_s(temp, "EWS%01d", tempws); return HWSend(temp); } RET_STATUS nsGEN::SPELLMANDevice::SetAPR(const _tAPRArgs& t) { m_t = t; //PRINTA_INFO("*********************Enter SetAPR,but do nothing**********************"); return RET_STATUS::RET_SUCCEED; //if (m_bExpSucc) //{ // if (m_DoseUnit.m_ExpMode->JSGet() == AttrKey::EXPMODE_TYPE::Single) // { // m_DoseUnit.m_ExpMode->Update(AttrKey::EXPMODE_TYPE::TOMO); // } // else if (m_DoseUnit.m_ExpMode->JSGet() == AttrKey::EXPMODE_TYPE::TOMO) // { // m_DoseUnit.m_ExpMode->Update(AttrKey::EXPMODE_TYPE::Single); // } //} //if (m_DoseUnit.m_ExpMode->JSGet() == AttrKey::EXPMODE_TYPE::Single) //{ // //PRINTA_INFO("Enter SetAPR Single"); // SetWS(m_DoseUnit.m_WS->JSGet()); // SetKV(t.fKV); // SetFocus(t.nFocus); // SetTechmode(t.nTechmode); // if (t.nTechmode == AttrKey::TECHMODE_V2TYPE::ET_MAS)//mas // { // return SetMAS(t.fMAS); // } // else if (t.nTechmode == AttrKey::TECHMODE_V2TYPE::ET_AEC)//aec // { // SetAECField(t.nAECField); // SetAECFilm(t.nAECFilm); // SetAECDensity(t.nAECDensity); // SetMA(t.fMA); // return SetMS(t.fMS); // } // else//time // { // SetMA(t.fMA); // return SetMS(t.fMS); // } //} //else if (m_DoseUnit.m_ExpMode->JSGet() == AttrKey::EXPMODE_TYPE::TOMO) //{ // //PRINTA_INFO("Enter SetAPR FLU"); // char temp[50] = { 0 }; // sprintf_s(temp, "FLK%03d", (int)(t.fKV)); // HWSend(temp); // sprintf_s(temp, "FLM%03d", (int)(10 * (t.fMA))); // HWSend(temp); // sprintf_s(temp, "FLS%03d", (int)(10 * (m_DoseUnit.m_FrameRate->Get()))); // return HWSend(temp); //} //else if (m_DoseUnit.m_ExpMode->JSGet() == AttrKey::EXPMODE_TYPE::CoutineSerial) //{ // //PRINTA_INFO("Enter SetAPR CF,but do nothing now."); // return RET_STATUS::RET_SUCCEED; //} } RET_STATUS nsGEN::SPELLMANDevice::QueryHE(int& value) { return RET_STATUS::RET_SUCCEED; } RET_STATUS nsGEN::SPELLMANDevice::QueryPostKV(float& value) { value = m_DoseUnit.m_PostKV->Get(); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsGEN::SPELLMANDevice::QueryPostMA(float& value) { value = m_DoseUnit.m_PostMA->Get(); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsGEN::SPELLMANDevice::QueryPostMS(float& value) { value = m_DoseUnit.m_PostMS->Get(); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsGEN::SPELLMANDevice::QueryPostMAS(float& value) { value = m_DoseUnit.m_PostMAS->Get(); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsGEN::SPELLMANDevice::Clear_DAP() { char temp[50] = "EDZ"; return HWSend(temp); } RET_STATUS nsGEN::SPELLMANDevice::GetValue_DAP(float& value) { value = m_DAP->Get(); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsGEN::SPELLMANDevice::StartMove() { //PRINTA_INFO("Enter startMove"); char temp[50] = { 0 }; if (m_DoseUnit.m_ExpMode->JSGet() != AttrKey::EXPMODE_TYPE::Single) { sprintf_s(temp, "FLS%03d", (int)(m_DoseUnit.m_FrameRate->Get() * 10)); //pps 需要放大10倍 HWSend(temp); } //点片EXO2 ,PF :EXO1 CF:EXO3 if (m_DoseUnit.m_ExpMode->JSGet() == AttrKey::EXPMODE_TYPE::Single) { sprintf_s(temp, "EXO%01d", (int)(2)); HWSend(temp); } else if (m_DoseUnit.m_ExpMode->JSGet() == AttrKey::EXPMODE_TYPE::TOMO) { sprintf_s(temp, "EXO%01d", (int)(1)); HWSend(temp); } else if (m_DoseUnit.m_ExpMode->JSGet() == AttrKey::EXPMODE_TYPE::CoutineSerial) { sprintf_s(temp, "EXO%01d", (int)(3)); HWSend(temp); } sprintf_s(temp, "TIC%01d", (int)(1)); HWSend(temp); //PRINTA_INFO("end startmove"); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsGEN::SPELLMANDevice::EndMove() { printf("enter EndMove\n"); //PRINTA_INFO("Enter endmove"); char temp[50]{ 0 }; sprintf_s(temp, "EXO%01d", (int)(0)); HWSend(temp); sprintf_s(temp, "TIC%01d", (int)(0)); HWSend(temp); SetFLFMode(to_string((int)AttrKey::GENERATOR_FLUMode::GENERATOR_FLMODE_NOTFLU)); printf("end EndMove\n"); //PRINTA_INFO("end EndMove"); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsGEN::SPELLMANDevice::SetGenSynState(int value) { return RET_STATUS::RET_SUCCEED; } RET_STATUS nsGEN::SPELLMANDevice::SetGenState(int value) { return RET_STATUS::RET_SUCCEED; } RET_STATUS nsGEN::SPELLMANDevice::SetExpMode(std::string value) { //PRINTA_INFO("Enter SetExpMode...%s",value); m_DoseUnit.m_ExpMode->Update(value); //退出CBCT,设置exp mode时,强制退出cbct,因为放在endmove中,偶发执行不到的问题。 SetFLFMode("0"); HWSend("TIC0"); if (m_DoseUnit.m_ExpMode->JSGet() == AttrKey::EXPMODE_TYPE::Single) { //PRINTA_INFO("Enter SetAPR Single kv=%f ma=%f",m_t.fKV,m_t.fMA); SetWS(m_DoseUnit.m_WS->JSGet()); if (abs(m_t.fKV) == 0) //如果上层传入参数为零,那么查询 { HWSend("RKV?"); } else { SetKV(m_t.fKV); } SetFocus(m_t.nFocus); SetTechmode(m_t.nTechmode); if (m_t.nTechmode == AttrKey::TECHMODE_V2TYPE::ET_MAS)//mas { SetMAS(m_t.fMAS); } else if (m_t.nTechmode == AttrKey::TECHMODE_V2TYPE::ET_AEC)//aec { SetAECField(m_t.nAECField); SetAECFilm(m_t.nAECFilm); SetAECDensity(m_t.nAECDensity); SetMA(m_t.fMA); SetMS(m_t.fMS); } else//time { if (abs(m_t.fMA) == 0) { HWSend("RMA?"); } else { SetMA(m_t.fMA); } SetMS(m_t.fMS); } } else if (m_DoseUnit.m_ExpMode->JSGet() == AttrKey::EXPMODE_TYPE::TOMO) { char temp[50] = { 0 }; sprintf_s(temp, "FLK%03d", (int)(m_DoseUnit.m_KV->Get())); HWSend(temp); sprintf_s(temp, "FLM%03d", (int)(10*(m_DoseUnit.m_MA->Get()))); HWSend(temp); sprintf_s(temp, "FLS%03d", (int)(10*(m_DoseUnit.m_FrameRate->Get()))); //PRINTA_INFO("Enter SetAPR TOMO kv=%d ma=%d", m_DoseUnit.m_KV->Get(), m_DoseUnit.m_MA->Get()); HWSend(temp); } //无论哪种模式,我都会设置FLF2= PF. 仅测试用,后续正式版本,得删除. char temp[50] = { 0 }; sprintf_s(temp, "FLF%01d", (int)(2)); HWSend(temp); //理论上来说,设置exp模式的时候,若点片,RPS主动设置为0. if (AttrKey::EXPMODE_TYPE::Single == value) { //PRINTA_INFO("now is Single mode, send RPS0"); SetRPS(0); } return RET_STATUS::RET_SUCCEED; } RET_STATUS nsGEN::SPELLMANDevice::SetFLFMode(std::string value) { char temp[50]{ 0 }; sprintf_s(temp, "RTS%s",value); return HWSend(temp); } RET_STATUS nsGEN::SPELLMANDevice::SetEXAMMode(std::string value) { return RET_STATUS::RET_SUCCEED; } RET_STATUS nsGEN::SPELLMANDevice::SetFrameRate(FLOAT frameRate) { m_DoseUnit.m_FrameRate->Update(frameRate); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsGEN::SPELLMANDevice::SetRPS(int rps) { char temp[50]{ 0 }; sprintf_s(temp, "RPS%03d", rps * 10); return HWSend(temp); } RET_STATUS nsGEN::SPELLMANDevice::RefreshData() { HWSend("RKV?"); HWSend("RMA?"); HWSend("RMS?"); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsGEN::SPELLMANDevice::SetExpEnable() { return HWSend("EXB1"); } RET_STATUS nsGEN::SPELLMANDevice::SetExpDisable() { return HWSend("EXB0"); } RET_STATUS nsGEN::SPELLMANDevice::Reset() { return HWSend("ERE1");//ERE1 = reset gen. } RET_STATUS nsGEN::SPELLMANDevice::HWSend(char* strCommand, int nTimeOut) { if (!m_SCF) return RET_STATUS::RET_FAILED; char strSendCommand[100] = { 0 }; int len = strlen(strCommand); int tmpSum = 0; for (int i = 0; i < len; i++) { tmpSum += (int)strCommand[i]; } char checkSum = char(tmpSum + 5); strSendCommand[0] = 0x02; memcpy(strSendCommand + 1, strCommand, len); strSendCommand[len + 1] = 0x03; strSendCommand[len + 2] = checkSum; printf("==OUT==: %s \n", strSendCommand); //PRINTA_INFO("==OUT==: %s \n", strSendCommand); int retLength; m_SCF.Lock(msTimeOut_Lock) .SendPacket(strSendCommand, strlen(strSendCommand), nTimeOut, retLength); Sleep(nTimeOut); return RET_STATUS::RET_SUCCEED; } //----------------------------------------------------------------------------- // ProcessCmd //----------------------------------------------------------------------------- void nsGEN::SPELLMANDevice::FireNotify(std::string key, std::string content) { EventCenter->OnNotify(1, key, content); } struct tFrameMapping { static const int MaxLen = 5; // 前缀不能超超过 5 个字符 ! using cbFun = std::function ; char strHead[MaxLen]; int NbOfCharOfHead; cbFun fun; tFrameMapping(char* str, int len, cbFun f) { assert(len < MaxLen); //len最大只能是4 strHead[0] = 0x02; //STX for (int i = 0; i < len; i++) //给strHead赋值 strHead[i + 1] = str[i]; NbOfCharOfHead = len + 1; fun = f; } }; static std::list arFrame; static bool DecodeFrame(const char* strFrame, int length); void nsGEN::SPELLMANDevice::OnCallBack() { auto HWNotProcess = [](const char* value, int length) -> void { printf("\n This commands didn't need to process!\n"); //PRINTA_INFO("\n This commands didn't need to process!\n"); }; auto HWKV = [this](const char* value, int length) -> void { assert(value); if (m_DoseUnit.m_KV->Update(atof(value))) FireNotify(AttrKey::KV, m_DoseUnit.m_KV->JSGet()); }; auto HWMAS = [this](const char* value, int length) { assert(value); float fmas = atof(value) / 1000.0; if (m_DoseUnit.m_Techmode->Get() == AttrKey::TECHMODE_V2TYPE::ET_TIME) { if (m_DoseUnit.m_MAS->Update(0)) FireNotify(AttrKey::MAS, m_DoseUnit.m_MAS->JSGet()); } else { if (m_DoseUnit.m_MAS->Update(fmas)) FireNotify(AttrKey::MAS, m_DoseUnit.m_MAS->JSGet()); } }; auto HWMA = [this](const char* value, int length) { assert(value); float fma = atof(value) / 100.0; if (m_DoseUnit.m_MA->Update(fma)) FireNotify(AttrKey::MA, m_DoseUnit.m_MA->JSGet()); }; auto HWMS = [this](const char* value, int length) { assert(value); if (m_DoseUnit.m_MS->Update(atof(value) / 100.0)) FireNotify(AttrKey::MS, m_DoseUnit.m_MS->JSGet()); }; auto HWFocus = [this](const char* value, int length) { assert(value); if (m_DoseUnit.m_Focus->Update(atoi(value))) FireNotify(AttrKey::FOCUS, m_DoseUnit.m_Focus->JSGet()); }; auto HWTechmode = [this](const char* value, int length) { assert(value); if (m_DoseUnit.m_Techmode->Update(atoi(value))) FireNotify(AttrKey::TECHMODE, m_DoseUnit.m_Techmode->JSGet()); }; auto HWAECField = [this](const char* value, int length) { assert(value); int nvalue = atoi(value); if (m_DoseUnit.m_AECField->Update(nvalue)) FireNotify(AttrKey::AECFIELD, m_DoseUnit.m_AECField->JSGet()); }; auto HWAECFilm = [this](const char* value, int length) { assert(value); if (m_DoseUnit.m_AECFilm->Update(atoi(value))) FireNotify(AttrKey::AECFILM, m_DoseUnit.m_AECFilm->JSGet()); }; auto HWAECDensity = [this](const char* value, int length) { assert(value); if (m_DoseUnit.m_AECDensity->Update(atoi(value))) FireNotify(AttrKey::AECDENSITY, m_DoseUnit.m_AECDensity->JSGet()); }; auto HWWS = [this](const char* value, int length) { assert(value); int nValue = atoi(value); if (m_DoseUnit.m_WS->Update(nValue)) { FireNotify(m_DoseUnit.m_WS->GetKey(), m_DoseUnit.m_WS->JSGet()); } }; auto HWPR = [this](const char* value, int length) { assert(value); int nValue = atoi(value); if (nValue == 2) { m_DoseUnit.m_GenSynState->Update(AttrKey::GENERATOR_RAD_READY); ResetEvent(m_hGenPostEvent); HWSend("PR2"); } else if (nValue == 1) { m_DoseUnit.m_GenSynState->Update(AttrKey::GENERATOR_RAD_PREPARE); HWSend("PR1"); } else if (nValue == 0) { m_DoseUnit.m_GenSynState->Update(AttrKey::GENERATOR_RAD_OFF); HWSend("PR0"); } FireNotify(m_DoseUnit.m_GenSynState->GetKey(), m_DoseUnit.m_GenSynState->JSGet()); }; auto HWXR = [this](const char* value, int length) { assert(value); int nValue = atoi(value); if (nValue == 1) { m_DoseUnit.m_GenSynState->Update(AttrKey::GENERATOR_RAD_XRAYON); } else if (nValue == 0) { m_DoseUnit.m_GenSynState->Update(AttrKey::GENERATOR_RAD_OFF); } FireNotify(m_DoseUnit.m_GenSynState->GetKey(), m_DoseUnit.m_GenSynState->JSGet()); }; auto HWAPDOSE = [this](const char* value, int length)//mas { assert(value); if(m_DoseUnit.m_PostMAS->Update(atof(value) / 1000.0)) FireNotify(m_DoseUnit.m_PostMAS->GetKey(), m_DoseUnit.m_PostMAS->JSGet()); //SetEvent(m_hGenPostEvent); }; auto HWATDOSE = [this](const char* value, int length) { assert(value); if(m_DoseUnit.m_PostMS->Update(atof(value))) FireNotify(m_DoseUnit.m_PostMS->GetKey(), m_DoseUnit.m_PostMS->JSGet()); //SetEvent(m_hGenPostEvent); }; auto HWDAP = [this](const char* value, int length) { //assert(value); //m_DoseUnit.m_da->Update(atof(value)); //FireNotify(m_DoseUnit.m_PostMS->GetKey(), m_DoseUnit.m_PostMS->JSGet()); //SetEvent(m_hGenPostEvent); }; auto HWERROR = [this](const char* value, int length) { assert(value); int nValue = atoi(value); if (nValue != 0) { char ErrorCode[10]{ "" }; sprintf_s(ErrorCode, "SPELLMANECOM_ERR_%d", nValue); int level = 1; m_MSGUnit->AddErrorMessage(ErrorCode, level, ""); } else { int level = 1; char ErrorCode[10]{ "" }; m_MSGUnit->DelErrorMessage(ErrorCode, level, ""); } }; auto HWWARN = [this](const char* value, int length) { assert(value); int nValue = atoi(value); if (nValue != 0) { char WarnCode[10]{ "" }; sprintf_s(WarnCode, "SPELLMANECOM_WARN_%d", nValue); int level = 1; m_MSGUnit->AddWarnMessage(WarnCode, level, ""); } else { int level = 1; char WarnCode[10]{ "" }; m_MSGUnit->AddWarnMessage(WarnCode, level, ""); } }; auto HWEHE = [this](const char* value, int length) { assert(value); if(m_DoseUnit.m_HE->Update(atoi(value))) FireNotify(m_DoseUnit.m_HE->GetKey(), m_DoseUnit.m_HE->JSGet()); }; auto HWFLK = [this](const char* value, int length) { assert(value); if (m_DoseUnit.m_KV->Update(atof(value))) FireNotify(AttrKey::KV, m_DoseUnit.m_KV->JSGet()); }; auto HWFLM = [this](const char* value, int length) { assert(value); if (m_DoseUnit.m_MA->Update(atof(value)/10.0)) FireNotify(AttrKey::MA, m_DoseUnit.m_MA->JSGet()); }; auto HWFLS = [this](const char* value, int length) { assert(value); if (m_DoseUnit.m_FrameRate->Update(atof(value)/10.0)) FireNotify(AttrKey::FRAMERATE, m_DoseUnit.m_FrameRate->JSGet()); }; auto HWFLX = [this](const char* value, int length) { assert(value); int nValue = atoi(value); if (nValue == 1) { m_DoseUnit.m_GenSynState->Update(AttrKey::GENERATOR_FLU_XRAYON); } else if (nValue == 0) { m_DoseUnit.m_GenSynState->Update(AttrKey::GENERATOR_FLU_XRAYOFF); } FireNotify(m_DoseUnit.m_GenSynState->GetKey(), m_DoseUnit.m_GenSynState->JSGet()); }; auto HWFLP = [this](const char* value, int length) { assert(value); int nValue = atoi(value); if (nValue == 1) { ////PRINTA_INFO("\n recv FLP1\n"); //FLP1尚未真正的ready. } else if (nValue == 4) { m_DoseUnit.m_GenSynState->Update(AttrKey::GENERATOR_FLU_READY); //根据全新定义 FLP4 才表示 ready。 } else if (nValue == 0) { m_DoseUnit.m_GenSynState->Update(AttrKey::GENERATOR_FLU_OFF); } FireNotify(m_DoseUnit.m_GenSynState->GetKey(), m_DoseUnit.m_GenSynState->JSGet()); }; // 有部分前缀是包含关系, 长的包含短的, 例如 KVS 包含了 KV. // 因此长的在前面, 短的在后面 // !!! Device 是个短寿命对象, 而 arFrame 是静态变量 !!! // !!! 因此, 在添加到 arFrame 之前, 务必先清零 !!! arFrame.clear(); arFrame.push_back(tFrameMapping("RKVI", 4, HWNotProcess)); arFrame.push_back(tFrameMapping("RKVD", 4, HWNotProcess)); arFrame.push_back(tFrameMapping("RMAI", 4, HWNotProcess)); arFrame.push_back(tFrameMapping("RMAD", 4, HWNotProcess)); arFrame.push_back(tFrameMapping("RMSI", 4, HWNotProcess)); arFrame.push_back(tFrameMapping("RMSD", 4, HWNotProcess)); arFrame.push_back(tFrameMapping("RMXI", 4, HWNotProcess)); arFrame.push_back(tFrameMapping("RMXD", 4, HWNotProcess)); arFrame.push_back(tFrameMapping("EXB", 3, HWNotProcess)); arFrame.push_back(tFrameMapping("ERE", 3, HWNotProcess)); arFrame.push_back(tFrameMapping("RR", 2, HWNotProcess)); arFrame.push_back(tFrameMapping("RPS", 3, HWNotProcess)); arFrame.push_back(tFrameMapping("EXO", 3, HWNotProcess)); arFrame.push_back(tFrameMapping("TIC", 3, HWNotProcess)); arFrame.push_back(tFrameMapping("RTS", 3, HWNotProcess)); arFrame.push_back(tFrameMapping("DSN", 3, HWNotProcess)); arFrame.push_back(tFrameMapping("RKV", 3, HWKV)); arFrame.push_back(tFrameMapping("RMX", 3, HWMAS)); arFrame.push_back(tFrameMapping("RMA", 3, HWMA)); arFrame.push_back(tFrameMapping("RMS", 3, HWMS)); arFrame.push_back(tFrameMapping("RET", 3, HWTechmode)); arFrame.push_back(tFrameMapping("RFO", 3, HWFocus)); arFrame.push_back(tFrameMapping("RFI", 3, HWAECField)); arFrame.push_back(tFrameMapping("RFS", 3, HWAECFilm)); arFrame.push_back(tFrameMapping("RFN", 3, HWAECDensity)); arFrame.push_back(tFrameMapping("EWS", 3, HWWS)); arFrame.push_back(tFrameMapping("PR", 2, HWPR)); arFrame.push_back(tFrameMapping("XR", 2, HWXR)); arFrame.push_back(tFrameMapping("RAP", 3, HWAPDOSE)); arFrame.push_back(tFrameMapping("RAT", 3, HWATDOSE)); arFrame.push_back(tFrameMapping("ERR", 3, HWERROR)); arFrame.push_back(tFrameMapping("EWN", 3, HWWARN)); arFrame.push_back(tFrameMapping("EHE", 3, HWEHE)); arFrame.push_back(tFrameMapping("FLK", 3, HWFLK)); arFrame.push_back(tFrameMapping("FLM", 3, HWFLM)); arFrame.push_back(tFrameMapping("FLS", 3, HWFLS)); arFrame.push_back(tFrameMapping("FLF", 3, HWNotProcess)); arFrame.push_back(tFrameMapping("FLP", 3, HWFLP)); arFrame.push_back(tFrameMapping("FLX", 3, HWFLX)); } bool nsGEN::SPELLMANDevice::StartHardwareStatusThread() { //PRINTA_INFO("enter Start HardwareStatus Thread "); if (m_pHardwareStatusThread == NULL) { DWORD m_HardwareStatusID; m_pHardwareStatusThread = CreateThread(0, 0, HardwareStatusThread, this, 0, &m_HardwareStatusID); if (m_pHardwareStatusThread == NULL) { //PRINTA_FATAL("Start HardwareStatus Thread Failed"); return false; } } return true; } DWORD nsGEN::SPELLMANDevice::HardwareStatusThread(LPVOID pParam) { SPELLMANDevice* pCurGen = (SPELLMANDevice*)pParam; if (pCurGen == NULL) { return false; } //PRINTA_INFO("HardwareStatusThread start"); while (true) { Sleep(2000); pCurGen->HWSend("EHE?"); } //PRINTA_INFO("HardwareStatusThread stop"); return true; } //----------------------------------------------------------------------------- // SPELLMANDriver //----------------------------------------------------------------------------- nsGEN::SPELLMANDriver::SPELLMANDriver() { m_bDemoConnected = false; } nsGEN::SPELLMANDriver::~SPELLMANDriver() { } auto nsGEN::SPELLMANDriver::CreateDevice(int index) -> std::unique_ptr { if (!m_SCF.isConnected()) return nullptr; auto dev = std::unique_ptr (new IODevice(new SPELLMANDevice(EventCenter, m_SCF))); return dev; } void nsGEN::SPELLMANDriver::FireNotify(int code, std::string key, std::string content) { EventCenter->OnNotify(code, key, content); } void nsGEN::SPELLMANDriver::Prepare() { m_SCFDllName = GetConnectDLL(m_ConfigFileName); super::Prepare(); } bool DATA_ACTION nsGEN::SPELLMANDriver::Connect() { ResDataObject Connection = GetConnectParam(m_ConfigFileName); //mLog::Info("connections:{$} \n", Connection.encode()); printf("connections:%s \n", Connection.encode()); //PRINTA_INFO("connections:%s \n", Connection.encode()); auto erCode = m_SCF.Connect(Connection.encode(), &nsGEN::SPELLMANDriver::callbackPackageProcess, SCF_PACKET_TRANSFER, 3000); if (erCode != SCF_ERR::SCF_SUCCEED) return false; auto rc = super::Connect(); if (!rc) return false; //return (erCode == SCF_ERR::SCF_SUCCEED); return true; } void nsGEN::SPELLMANDriver::Disconnect() { super::Disconnect(); m_SCF.Disconnect(); m_bDemoConnected = false; } bool nsGEN::SPELLMANDriver::isConnected() const { return super::isConnected(); } std::string nsGEN::SPELLMANDriver::DriverProbe() { ResDataObject r_config, HardwareInfo; if (r_config.loadFile(m_ConfigFileName.c_str())) { HardwareInfo.add("MajorID", r_config["CONFIGURATION"]["MajorID"]); HardwareInfo.add("MinorID", r_config["CONFIGURATION"]["MinorID"]); HardwareInfo.add("VendorID", r_config["CONFIGURATION"]["VendorID"]); HardwareInfo.add("ProductID", r_config["CONFIGURATION"]["ProductID"]); HardwareInfo.add("SerialID", r_config["CONFIGURATION"]["SerialID"]); } else { HardwareInfo.add("MajorID", "Generator"); HardwareInfo.add("MinorID", "Dr"); HardwareInfo.add("VendorID", "SPELLMAN"); HardwareInfo.add("ProductID", "HF"); HardwareInfo.add("SerialID", "Drv"); } string ret = HardwareInfo.encode(); return ret; } std::string nsGEN::SPELLMANDriver::GetResource() { ResDataObject temp; if (!temp.loadFile(m_ConfigFileName.c_str())) return std::string(); auto r_config = temp["CONFIGURATION"]; for (auto& Item : m_ConfigInfo) { string key = Item.GetKey(); if (key == ConfKey::CcosGeneratorType) { Item.SetCurrentValue(((string)r_config["VendorID"]).c_str()); } else if (key == ConfKey::CcosGeneratorModel) { Item.SetCurrentValue(((string)r_config["ProductID"]).c_str()); } else if (key == ConfKey::CcosWSTable || key == ConfKey::CcosWSWall || key == ConfKey::CcosWSFree || key == ConfKey::CcosWSTomo || key == ConfKey::CcosWSConventional) { Item.SetCurrentValue(((string)r_config[key.c_str()]).c_str()); } else if (key == ConfKey::CcosSynTable || key == ConfKey::CcosSynWall || key == ConfKey::CcosSynFree || key == ConfKey::CcosSynTomo || key == ConfKey::CcosSynConventional) { Item.SetCurrentValue(((string)r_config[key.c_str()]).c_str()); } else if (key == ConfKey::CcosSCFType) { Item.SetCurrentValue(((string)r_config["connections"][0]["type"]).c_str()); } else if (key == ConfKey::CcosSCFPort || key == ConfKey::CcosSCFBaudrate || key == ConfKey::CcosSCFBytesize || key == ConfKey::CcosSCFParity || key == ConfKey::CcosSCFStopbits || key == ConfKey::CcosSCFIP) { if (r_config["connections"][0].GetFirstOf(key.c_str()) >= 0) { Item.SetCurrentValue(((string)r_config["connections"][0][key.c_str()]).c_str()); } } } ResDataObject resAttr, resDescription; for (auto Item : m_ConfigInfo) { resAttr.add(Item.GetKey(), Item.GetCurrentValue()); resDescription.add(Item.GetKey(), Item.GetDescription()); } ResDataObject resDeviceResource; resDeviceResource.add(ConfKey::CcosGeneratorAttribute, resAttr); resDeviceResource.add(ConfKey::CcosGeneratorDescription, resDescription); string res = resDeviceResource.encode(); printf("resDeviceResource :%s \n", resDeviceResource.encode()); //PRINTA_INFO("resDeviceResource :%s \n", resDeviceResource.encode()); return res; } std::string nsGEN::SPELLMANDriver::DeviceProbe() { ResDataObject r_config, HardwareInfo; if (r_config.loadFile(m_ConfigFileName.c_str())) { HardwareInfo.add("MajorID", r_config["CONFIGURATION"]["MajorID"]); HardwareInfo.add("MinorID", r_config["CONFIGURATION"]["MinorID"]); HardwareInfo.add("VendorID", r_config["CONFIGURATION"]["VendorID"]); HardwareInfo.add("ProductID", r_config["CONFIGURATION"]["ProductID"]); HardwareInfo.add("SerialID", r_config["CONFIGURATION"]["SerialID"]); } else { HardwareInfo.add("MajorID", "Generator"); HardwareInfo.add("MinorID", "Dr"); HardwareInfo.add("VendorID", "SPELLMAN"); HardwareInfo.add("ProductID", "HF"); HardwareInfo.add("SerialID", "1234"); } string ret = HardwareInfo.encode(); return ret; } void nsGEN::SPELLMANDriver::Dequeue(const char* Packet, DWORD Length) { DecodeFrame(Packet, Length); } PACKET_RET nsGEN::SPELLMANDriver::callbackPackageProcess(const char* RecData, DWORD nLength, DWORD& PacketLength) { if (nLength < 1) { printf("nLength < 1, nLength==%d \n", nLength); //PRINTA_INFO("nLength < 1, nLength==%d \n", nLength); return PACKET_USELESS; } for (DWORD i = 0; i < nLength - 1; i++) { //1 首先寻找包头 if (RecData[i]==0x02) { if (i!=0) { PacketLength = i; //i之前的数据,全部扔掉 char strtemp[100] = { 0 }; memcpy(strtemp, RecData, i); strtemp[PacketLength + 1] = 0; printf("==IN error data ==:%s,PacketLength=%d,nLength=%d\n", strtemp, PacketLength, nLength); //for test //for (int j = 0; j < nLength; j++) //{ // printf("%2X,", RecData[j]); //} //printf("\n"); return PACKET_USELESS; } } if (RecData[i] == 0x03) { PacketLength = i + 2; //+2 because STX , sum. char strtemp[100] = { 0 }; memcpy(strtemp, RecData, i); // STX+RKC005(not include 03 + sum); //only 复制 0x03之前的数据,这样解析时,后面的03 ,sum 都不要了。 strtemp[PacketLength + 1] = 0; printf("==IN==:%s\n", strtemp); //PRINTA_INFO("==IN==:%s\n", strtemp); return PACKET_ISPACKET; } } return PACKET_NOPACKET; } //----------------------------------------------------------------------------- // DecodeFrame //----------------------------------------------------------------------------- static bool DecodeFrame(const char* strFrame, int length) { auto pr = [strFrame, length](const tFrameMapping& Item) { for (int i = 0; i < Item.NbOfCharOfHead; i++) { if (strFrame[i] != Item.strHead[i]) { return false; } } return true; }; auto found = std::find_if(arFrame.begin(), arFrame.end(), pr); if (found == arFrame.end()) { return false; } const auto& Item = *found; auto pc = strFrame; char data[100] = { 0 }; memcpy(data, strFrame + Item.NbOfCharOfHead, length - Item.NbOfCharOfHead - 2); //pc += Item.NbOfCharOfHead; //---------jk++:pc is value. why? plus NbOfCharOfHead. 意思是pc的指针后移几个数, Item.fun(data, length - Item.NbOfCharOfHead - 2);//第二个参数 不重要 return true; } //----------------------------------------------------------------------------- // GetIODriver & CreateIODriver //----------------------------------------------------------------------------- static nsGEN::SPELLMANDriver gIODriver; extern "C" CCOS::Dev::IODriver * __cdecl GetIODriver() // 返回静态对象的引用, 调用者不能删除 ! { return &gIODriver; } extern "C" CCOS::Dev::IODriver * __cdecl CreateIODriver() // 返回新对象, 调用者必须自行删除此对象 ! { return new nsGEN::SPELLMANDriver(); }