diff --git a/vmmTbl.Makefile b/vmmTbl.Makefile index 585f59a18bcf9fabf39a65850bd2db8a727813f3..4654223b737786a2eea95dd586d164d52cd035dc 100644 --- a/vmmTbl.Makefile +++ b/vmmTbl.Makefile @@ -14,6 +14,7 @@ SUBS = $(APPDB)/channels.sub LIB_SYS_LIBS += vmmapi SOURCES += $(APPSRC)/vmm_tbl.cpp +SOURCES += $(APPSRC)/Utils.cpp DBDS += $(APPSRC)/vmm_tbl.dbd diff --git a/vmmTblApp/Db/channels.template b/vmmTblApp/Db/channels.template index 4347f5bb476f29a698029146e190c85d780f9cc8..03ee4d6d3ca9db9827c22ebff8014b85aded0e5f 100644 --- a/vmmTblApp/Db/channels.template +++ b/vmmTblApp/Db/channels.template @@ -9,9 +9,19 @@ record(aao, "$(P)$(R)$(HYB)$(VMM)$(C)$(CH)-S") { field(DTYP, "asynInt8ArrayOut") field(NELM, "64") field(FTVL, "CHAR") + field(FLNK, "$(P)$(R)$(HYB)$(VMM)$(C)$(CH)-R") field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_$(VMM)_$(CH)") } +record(aai, "$(P)$(R)$(HYB)$(VMM)$(C)$(CH)-R") { + field(DESC, "Get $(CH) channels array") + field(DTYP, "asynInt8ArrayIn") + field(NELM, "64") + field(FTVL, "CHAR") + field(SCAN, "I/O Intr") + field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_$(VMM)_$(CH)") +} + record(bo, "$(P)$(R)$(HYB)$(VMM)$(C)All$(CH)-S") { field(DESC, "Set all $(CH) channels") field(VAL, "0") diff --git a/vmmTblApp/Db/hybrid.template b/vmmTblApp/Db/hybrid.template index 323e111b4e66dd9faadf2d191f4f11baf436e5c1..27703968a02ee4a7f8d276fc93876b1b87d0bae0 100644 --- a/vmmTblApp/Db/hybrid.template +++ b/vmmTblApp/Db/hybrid.template @@ -2,12 +2,160 @@ record(stringin, "$(P)$(R)Hyb$(HYB)FwVersion-R") { field(DESC, "Hybrid $(HYB) Firmware version") field(DTYP, "asynOctetRead") field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_FW_VERSION") + field(PINI, "YES") field(SCAN, "I/O Intr") } +record(mbbo, "$(P)$(R)Hyb$(HYB)Skew-S"){ + field(DESC, "Hybrid's #$(HYB) Skew") + field(DTYP, "asynInt32") + field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_SKEW") + field(ZRST, "0 ns") + field(ZRVL, "0") + field(ONST, "2.83921 ns") + field(ONVL, "1") + field(TWST, "5.67842 ns") + field(TWVL, "2") + field(THST, "8.51764 ns") + field(THVL, "3") + field(FRST, "11.3568 ns") + field(FRVL, "4") + field(FVST, "14.1961 ns") + field(FVVL, "5") + field(SXST, "17.0353 ns") + field(SXVL, "6") + field(SVST, "19.8545 ns") + field(SVVL, "7") + field(EIST, "22.7137 ns") + field(EIVL, "8") + field(NIST, "25.5529 ns") + field(NIVL, "9") + field(TEST, "28.3921 ns") + field(TEVL, "10") + field(ELST, "31.2313 ns") + field(ELVL, "11") + field(TVST, "34.0705 ns") + field(TVVL, "12") + field(TTST, "36.9098 ns") + field(TTVL, "13") + field(FTST, "39.749 ns") + field(FTVL, "14") + field(FFST, "42.5882 ns") + field(FFVL, "15") + field(FLNK, "$(P)$(R)Hyb$(HYB)Skew-RB") +} + +record(mbbi, "$(P)$(R)Hyb$(HYB)Skew-RB"){ + field(DESC, "Hybrid's #$(HYB) Skew") + field(DTYP, "asynInt32") + field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_SKEW") + field(ZRST, "0 ns") + field(ZRVL, "0") + field(ONST, "2.83921 ns") + field(ONVL, "1") + field(TWST, "5.67842 ns") + field(TWVL, "2") + field(THST, "8.51764 ns") + field(THVL, "3") + field(FRST, "11.3568 ns") + field(FRVL, "4") + field(FVST, "14.1961 ns") + field(FVVL, "5") + field(SXST, "17.0353 ns") + field(SXVL, "6") + field(SVST, "19.8545 ns") + field(SVVL, "7") + field(EIST, "22.7137 ns") + field(EIVL, "8") + field(NIST, "25.5529 ns") + field(NIVL, "9") + field(TEST, "28.3921 ns") + field(TEVL, "10") + field(ELST, "31.2313 ns") + field(ELVL, "11") + field(TVST, "34.0705 ns") + field(TVVL, "12") + field(TTST, "36.9098 ns") + field(TTVL, "13") + field(FTST, "39.749 ns") + field(FTVL, "14") + field(FFST, "42.5882 ns") + field(FFVL, "15") + field(SCAN, "I/O Intr") + field(PINI, "YES") +} + +record(mbbo, "$(P)$(R)Hyb$(HYB)Width-S"){ + field(DESC, "Hybrid's #$(HYB) Width") + field(DTYP, "asynInt32") + field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_WIDTH") + field(ZRST, "128 x 22.7137") + field(ZRVL, "0") + field(ONST, "64 x 22.7137") + field(ONVL, "1") + field(TWST, "32 x 22.7137") + field(TWVL, "2") + field(THST, "16 x 22.7137") + field(THVL, "3") + field(FRST, "8 x 22.7137") + field(FRVL, "4") + field(FVST, "4 x 22.7137") + field(FVVL, "5") + field(SXST, "2 x 22.7137") + field(SXVL, "6") + field(SVST, "1 x 22.7137") + field(SVVL, "7") + field(FLNK, "$(P)$(R)Hyb$(HYB)Width-RB") +} + +record(mbbi, "$(P)$(R)Hyb$(HYB)Width-RB"){ + field(DESC, "Hybrid's #$(HYB) Width") + field(DTYP, "asynInt32") + field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_WIDTH") + field(PINI, "YES") + field(ZRST, "128 x 22.7137") + field(ZRVL, "0") + field(ONST, "64 x 22.7137") + field(ONVL, "1") + field(TWST, "32 x 22.7137") + field(TWVL, "2") + field(THST, "16 x 22.7137") + field(THVL, "3") + field(FRST, "8 x 22.7137") + field(FRVL, "4") + field(FVST, "4 x 22.7137") + field(FVVL, "5") + field(SXST, "2 x 22.7137") + field(SXVL, "6") + field(SVST, "1 x 22.7137") + field(SVVL, "7") + field(SCAN, "I/O Intr") +} + +record(bo, "$(P)$(R)Hyb$(HYB)Pol-S") { + field(DESC, "Hybrid's #$(HYB) Polarity") + field(DTYP, "asynInt32") + field(VAL, "0") + field(ZNAM, "positive") + field(ONAM, "negative") + field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_POLARITY") +} + +record(bi, "$(P)$(R)Hyb$(HYB)Pol-RB") { + field(DESC, "Hybrid's #$(HYB) Polarity") + field(DTYP, "asynInt32") + field(VAL, "0") + field(ZNAM, "positive") + field(ONAM, "negative") + field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_POLARITY") + field(SCAN, "I/O Intr") + field(PINI, "YES") +} + record(stringin, "$(P)$(R)Hyb$(HYB)ID-R") { field(DESC, "Hybrid $(HYB) ID") field(DTYP, "asynOctetRead") + field(PINI, "YES") field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_ID") field(SCAN, "I/O Intr") } @@ -15,12 +163,15 @@ record(stringin, "$(P)$(R)Hyb$(HYB)ID-R") { record(stringin, "$(P)$(R)Hyb$(HYB)GeoPos-R") { field(DESC, "Hybrid $(HYB) Geo Position") field(DTYP, "asynOctetRead") + field(PINI, "YES") field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_GEOPOS") field(SCAN, "I/O Intr") } record(mbbi, "$(P)$(R)Hyb$(HYB)LinkStatus-R") { field(DESC, "Hybrid $(HYB) Link Status") + field(PINI, "YES") + field(DTYP, "asynInt32") field(ZRST, "not connected") field(ZRVL, "0") field(ONST, "start alignment") @@ -34,6 +185,5 @@ record(mbbi, "$(P)$(R)Hyb$(HYB)LinkStatus-R") { field(FVST, "acq") field(FVVL, "5") field(SCAN, "I/O Intr") - field(DTYP, "asynInt32") field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))HYB_$(HYB)_LINK_STATUS") } diff --git a/vmmTblApp/Db/vmm_tbl.template b/vmmTblApp/Db/vmm_tbl.template index 26af164409de408eac247592aefa274c0e410f28..350c05d9139991f65b7b715cd9d11b15598cf731 100644 --- a/vmmTblApp/Db/vmm_tbl.template +++ b/vmmTblApp/Db/vmm_tbl.template @@ -56,3 +56,11 @@ record(bo, "$(P)$(R)Acquire-S") { field(DTYP, "asynInt32") field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))VMM_FEN_ACQUIRE") } + +record(ai, "$(P)$(R)RegBankVersion-R"){ + field(DESC, "Register bank version") + field(PINI, "YES") + field(DTYP, "asynInt32") + field(INP, "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))REG_BANK_VERSION") + field(SCAN, "I/O Intr") +} \ No newline at end of file diff --git a/vmmTblApp/src/Utils.cpp b/vmmTblApp/src/Utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4f21ae82b0bb1ae9419aba6e1828aa52bf2557fc --- /dev/null +++ b/vmmTblApp/src/Utils.cpp @@ -0,0 +1,63 @@ +#include <bits/stdc++.h> + +#include "Utils.h" + +/** + * @brief Gets index of number in vector. + * @param vec Vector to find number in + * @param function number to find. + * @return -1 if number is not found. -2 if number is repeated. Index of element if number is found. + **/ +int VecUtils::getIndex(std::vector<int>& vec, int function){ + + int c = std::count(vec.begin(), vec.end(), function); + if (c == 0) return -1; + if (c > 1) return -2; + + auto it = std::find(vec.begin(), vec.end(), function); + + if (it != vec.end()) return std::distance(vec.begin(), it); + + return -1; + +} + +/** + * @brief Gets two indexes of number in vector<vector<int>>. + * @param vec Vector to find number in + * @param function number to find. + * @param hyb_index reference to put the hybrid index in. + * @param vmm_index reference to put the vmm index in. + * @return -1 if number is not found. -2 if number is repeated. 0 if number is found. + **/ +int VecUtils::getIndex(std::vector<std::vector<int>>& vec, int function, int &hyb_index, int &vmm_index) { + hyb_index = -1; + vmm_index = -1; + + int occurrences = 0; + + for (size_t i = 0; i < vec.size(); ++i) { + auto& subvec = vec[i]; + auto it = std::find(subvec.begin(), subvec.end(), function); + + if (it != subvec.end()) { + ++occurrences; + if (occurrences > 1) { + hyb_index = -2; + vmm_index = -2; + return -2; // Duplicated + } + + hyb_index = static_cast<int>(i); + vmm_index = static_cast<int>(std::distance(subvec.begin(), it)); + } + } + + if (occurrences == 0) { + hyb_index = -1; + vmm_index = -1; + return -1; // Not found + } + + return 0; // Found exactly once +} \ No newline at end of file diff --git a/vmmTblApp/src/Utils.h b/vmmTblApp/src/Utils.h new file mode 100644 index 0000000000000000000000000000000000000000..f6880efe93f850e7ad8cb691c6fa541a9bb59554 --- /dev/null +++ b/vmmTblApp/src/Utils.h @@ -0,0 +1,10 @@ +// Generic utilities for the module + +#include <vector> + +namespace VecUtils{ + +int getIndex(std::vector<int>&, int function); +int getIndex(std::vector<std::vector<int>>&, int function, int &hyb_index, int &vmm_index); + +} \ No newline at end of file diff --git a/vmmTblApp/src/vmm_tbl.cpp b/vmmTblApp/src/vmm_tbl.cpp index 4b5ce9c8fb5991d775b054b2b64e080aa8dfea42..b2c535efbd33681fd10a2c6490adf3cfee20853a 100644 --- a/vmmTblApp/src/vmm_tbl.cpp +++ b/vmmTblApp/src/vmm_tbl.cpp @@ -6,8 +6,7 @@ VMMTbl::VMMTbl(RMM* rmm, const char *FENPortName, int ring, int node, int hybrid asynInt8ArrayMask | asynInt32Mask | asynInt64Mask | asynDrvUserMask | asynFloat64Mask | asynOctetMask, // Interfaces that we implement asynInt8ArrayMask | asynInt64Mask | asynInt32ArrayMask | asynFloat64Mask | asynInt32Mask | asynOctetMask, // Interfaces that do callbacks ASYN_MULTIDEVICE | ASYN_CANBLOCK, 1, /* ASYN_CANBLOCK=1, ASYN_MULTIDEVICE=1, autoConnect=1 */ - 0, 0), - number_hybrids(hybrids) + 0, 0) { pVmmAPI = FrontEndFactory::createAndRegister<VMMAPI>( @@ -15,183 +14,346 @@ VMMTbl::VMMTbl(RMM* rmm, const char *FENPortName, int ring, int node, int hybrid ring, node, "VmmTbl", - vmm_tbl_register_map); + vmm_tbl_register_map, + hybrids); createEpicsParams(); - setInitialEpicsParams(); rmm->updateTopologyPvs(ring, node, "vmmTbl"); - if (rmm->getRMMAPI()->checkRings() == rmmSuccess) { - for (int hyb = 0; hyb < number_hybrids; hyb++) { - pVmmAPI->enableHybrid(hyb, true); - setStringParam(vmmHybFwVersion_[hyb], pVmmAPI->readFwVersion(hyb).c_str()); - setStringParam(vmmHybId_[hyb], pVmmAPI->readIDChip(hyb).c_str()); - setStringParam(vmmHybGeoPos_[hyb], pVmmAPI->readGeoPos(hyb).c_str()); - setIntegerParam(vmmHybLinkStatus_[hyb], std::stoi(pVmmAPI->checkLinkStatus(hyb))); + +} + +asynStatus VMMTbl::readInt32(asynUser *pasynUser, epicsInt32 *value) { + int function = pasynUser->reason; + asynStatus status = asynSuccess; + uint32_t val; + int tmp_val; + bool tmp_val_bool; + uint8_t tmp_val_uint8; + int param_index; + + if (function < FIRST_VMM_PARAM) { + return asynPortDriver::readInt32(pasynUser, value); + } + + if (function == vmmRegBankVersion) { + vmmStatus result = this->pVmmAPI->getRegBankVersion(val); + if (result != vmmSuccess) status = asynError; + *value = val; + param_index = 10000; /// \todo So endOfReadInt32 won't return asynError; Maybe improve mechanism? + goto endOfReadInt32; + } + + //Search for parameter in all parameter vectors. If found, execute correct function for specific hybrid. + param_index = VecUtils::getIndex(vmmHybSkew_, function); + if (param_index >= 0) { + this->pVmmAPI->getSkew(param_index, tmp_val_uint8); + *value = tmp_val_uint8; + goto endOfReadInt32; + } + + param_index = VecUtils::getIndex(vmmHybLinkStatus_, function); + if (param_index >= 0) { + this->pVmmAPI->checkLinkStatus(param_index, tmp_val); + *value = tmp_val; + goto endOfReadInt32; + } + + param_index = VecUtils::getIndex(vmmHybWidth_, function); + if (param_index >= 0) { + this->pVmmAPI->getWidth(param_index, tmp_val_uint8); + *value = tmp_val_uint8; + goto endOfReadInt32; + } + + param_index = VecUtils::getIndex(vmmHybPolarity_, function); + if (param_index >= 0) { + this->pVmmAPI->getHybPolarity(param_index, tmp_val_bool); + *value = tmp_val_bool; + goto endOfReadInt32; + } + + endOfReadInt32: + if (param_index < 0) { + *value = 0; + return asynError; + } + + setIntegerParam(function, *value); + callParamCallbacks(); + + return asynSuccess; + +} + +asynStatus VMMTbl::readOctet(asynUser *pasynUser, char *value, + size_t nChars, size_t *nActual, + int *eomReason) +{ + + int status = asynSuccess; + int function = pasynUser->reason; + std::string read = ""; + + /* If this parameter belongs to a base class call its method */ + if (function < FIRST_VMM_PARAM) { + status = asynPortDriver::readOctet(pasynUser, value, nChars, nActual, + eomReason); + return (asynStatus)status; + } + + //Search for parameter in all parameter vectors. If found, execute correct function for specific hybrid. + int param_index = VecUtils::getIndex(vmmHybFwVersion_, function); + if (param_index >= 0) { + this->pVmmAPI->readFwVersion(param_index, read); + goto endOfReadOctet; } + + param_index = VecUtils::getIndex(vmmHybId_, function); + if (param_index >= 0) { + this->pVmmAPI->readIDChip(param_index, read); + goto endOfReadOctet; + } + + param_index = VecUtils::getIndex(vmmHybGeoPos_, function); + if (param_index >= 0) { + this->pVmmAPI->readGeoPos(param_index, read); + goto endOfReadOctet; } + + endOfReadOctet: + if (param_index < 0) { + value[0] = '\0'; + *nActual = 1; + return asynError; + } + size_t copy_size = std::min(read.size(), nChars); + strncpy(value, read.c_str(), copy_size); + setStringParam(function, value); + value[copy_size] = '\0'; + *nActual = copy_size; + *eomReason = ASYN_EOM_END; + callParamCallbacks(); + + return asynSuccess; + } -void VMMTbl::setInitialEpicsParams() { - puts("set_initial_epics_params"); +asynStatus VMMTbl::createParamAndStoreInVector(std::string paramName, asynParamType typ, + std::vector<int>* vectorToStore){ + + int paramIndex; + asynStatus status = createParam(paramName.c_str(), typ, ¶mIndex); + if (status != asynSuccess) { + asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, + "%s:%s: Failed to create paramter %s.\n", + driverName, __FUNCTION__, paramName.c_str()); + return asynError; + } + vectorToStore->push_back(paramIndex); + return asynSuccess; + } asynStatus VMMTbl::createEpicsParams() { - createParam("SEL_ANALOG_MONITOR_VMM0", asynParamInt32, &vmmSelectMonitorVMM0_); - createParam("SEL_ANALOG_MONITOR_VMM1", asynParamInt32, &vmmSelectMonitorVMM1_); - createParam("READ_ADC_VMMS", asynParamInt32, &vmmProcessReadMonitorVMMs_); - createParam("ADC_VALUE_VMM0", asynParamFloat64, &vmmMonitorValueVMM0_); - createParam("ADC_VALUE_VMM1", asynParamFloat64, &vmmMonitorValueVMM1_); - createParam("VMM_FEN_ACQUIRE", asynParamInt32, &vmmAcquire_); - - for (int hyb = 0; hyb < number_hybrids; hyb++) { - std::ostringstream param_name; - param_name << "HYB_" << hyb <<"_FW_VERSION"; - createParam(param_name.str().c_str(), asynParamOctet, &vmmHybFwVersion_[hyb]); - param_name.str(""); - param_name << "HYB_" << hyb <<"_ID"; - createParam(param_name.str().c_str(), asynParamOctet, &vmmHybId_[hyb]); - param_name.str(""); - param_name << "HYB_" << hyb <<"_GEOPOS"; - createParam(param_name.str().c_str(), asynParamOctet, &vmmHybGeoPos_[hyb]); - param_name.str(""); - param_name << "HYB_" << hyb <<"_LINK_STATUS"; - createParam(param_name.str().c_str(), asynParamInt32, &vmmHybLinkStatus_[hyb]); - for (int vmm=0; vmm < VMMS_PER_HYBRID; vmm++) - { - param_name.str(""); - param_name << "HYB_" << hyb <<"_" << vmm << "_ST"; - createParam(param_name.str().c_str(), asynParamInt8Array, &vmmST_[hyb][vmm]); - param_name.str(""); - param_name << "HYB_" << hyb <<"_" << vmm << "_SC"; - createParam(param_name.str().c_str(), asynParamInt8Array, &vmmSC_[hyb][vmm]); - param_name.str(""); - param_name << "HYB_" << hyb <<"_" << vmm << "_SL"; - createParam(param_name.str().c_str(), asynParamInt8Array, &vmmSL_[hyb][vmm]); - param_name.str(""); - param_name << "HYB_" << hyb <<"_" << vmm << "_STH"; - createParam(param_name.str().c_str(), asynParamInt8Array, &vmmSTH_[hyb][vmm]); - param_name.str(""); - param_name << "HYB_" << hyb <<"_" << vmm << "_SM"; - createParam(param_name.str().c_str(), asynParamInt8Array, &vmmSM_[hyb][vmm]); - param_name.str(""); - param_name << "HYB_" << hyb <<"_" << vmm << "_SMX"; - createParam(param_name.str().c_str(), asynParamInt8Array, &vmmSMX_[hyb][vmm]); + + createParam("REG_BANK_VERSION", asynParamInt32, &vmmRegBankVersion); + + std::tuple<std::string, asynParamType, std::vector<int>*> + hyb_params_to_create[7] = {{"_FW_VERSION", asynParamOctet, &vmmHybFwVersion_}, + {"_ID", asynParamOctet, &vmmHybId_}, + {"_GEOPOS", asynParamOctet, &vmmHybGeoPos_}, + {"_LINK_STATUS", asynParamInt32, &vmmHybLinkStatus_}, + {"_SKEW", asynParamInt32, &vmmHybSkew_}, + {"_WIDTH", asynParamInt32, &vmmHybWidth_}, + {"_POLARITY", asynParamInt32, &vmmHybPolarity_}}; + + std::ostringstream param_name; + + for (int hyb = 0; hyb < this->pVmmAPI->getNumHybrids(true); hyb++) { + + for (const auto& hyb_param : hyb_params_to_create){ + const std::string& key = std::get<0>(hyb_param); + asynParamType typ = std::get<1>(hyb_param); + std::vector<int>* vec = std::get<2>(hyb_param); + createParamAndStoreInVector("HYB_" + std::to_string(hyb) + key, typ, vec); } + + std::vector<int> SC, SL, ST, STH, SM, SMX; + + for (int vmm=0; vmm < VMMS_PER_HYBRID; vmm++) { + + + param_name.str(""); + param_name << "HYB_" << hyb <<"_" << vmm << "_SC"; + createParamAndStoreInVector(param_name.str(), asynParamInt8Array, &SC); + + param_name.str(""); + param_name << "HYB_" << hyb <<"_" << vmm << "_SL"; + createParamAndStoreInVector(param_name.str(), asynParamInt8Array, &SL); + + param_name.str(""); + param_name << "HYB_" << hyb <<"_" << vmm << "_ST"; + createParamAndStoreInVector(param_name.str(), asynParamInt8Array, &ST); + + param_name.str(""); + param_name << "HYB_" << hyb <<"_" << vmm << "_STH"; + createParamAndStoreInVector(param_name.str(), asynParamInt8Array, &STH); + + param_name.str(""); + param_name << "HYB_" << hyb <<"_" << vmm << "_SM"; + createParamAndStoreInVector(param_name.str(), asynParamInt8Array, &SM); + + param_name.str(""); + param_name << "HYB_" << hyb <<"_" << vmm << "_SMX"; + createParamAndStoreInVector(param_name.str(), asynParamInt8Array, &SMX); + + } + + this->vmmSC_.push_back(SC); + this->vmmSL_.push_back(SL); + this->vmmST_.push_back(ST); + this->vmmSTH_.push_back(STH); + this->vmmSM_.push_back(SM); + this->vmmSMX_.push_back(SMX); + } return asynSuccess; } asynStatus VMMTbl::writeInt32(asynUser *pasynUser, epicsInt32 value) { + asynStatus status = asynSuccess; + vmmStatus vmm_stat; int function = pasynUser->reason; + int param_index = -1; - if ((value) && (function == vmmProcessReadMonitorVMMs_)) { - int adc_sensor = 0; - for (int vmm = 0; vmm <= 1; vmm++) { - getIntegerParam(vmmSelectMonitorVMM0_ + vmm, &adc_sensor); - std::cout << "adc_sensor" << adc_sensor << std::endl; - pVmmAPI->getHybrid(0).getVMM(vmm).setRegister("sm5_sm0", adc_sensor + 64); - pVmmAPI->configVMM(0, vmm); - int adc_read = pVmmAPI->readADC(0, vmm); - - std::cout << "adc_read" << adc_read << std::endl; - - if (adc_sensor == 3) { - double temperature = (725 - adc_read) / 1.85; - setDoubleParam(vmmMonitorValueVMM0_ + vmm, temperature); - } - else { - setDoubleParam(vmmMonitorValueVMM0_ + vmm, adc_read); - } - } + // if (function == vmmAcquire_) { + + // if (value) pVmmAPI->acquire(true); + // else pVmmAPI->acquire(false); + + // for (int hyb = 0; hyb < number_hybrids; hyb++) + // setIntegerParam(vmmHybLinkStatus_[hyb], std::stoi(pVmmAPI->checkLinkStatus(hyb))); + // } + + if (function < FIRST_VMM_PARAM) { + return asynPortDriver::writeInt32(pasynUser, value); } - else if (function == vmmAcquire_) { - - if (value) pVmmAPI->acquire(true); - else pVmmAPI->acquire(false); + //Search for parameter in all parameter vectors. If found, execute correct function for specific hybrid. + param_index = VecUtils::getIndex(vmmHybSkew_, function); + if (param_index >= 0) { + vmm_stat = this->pVmmAPI->setSkew(param_index, value); + if (vmm_stat != vmmSuccess) status = asynError; + goto endOfWriteInt32; + } + + param_index = VecUtils::getIndex(vmmHybWidth_, function); + if (param_index >= 0) { + vmm_stat = this->pVmmAPI->setWidth(param_index, value); + if (vmm_stat != vmmSuccess) status = asynError; + goto endOfWriteInt32; + } + + param_index = VecUtils::getIndex(vmmHybPolarity_, function); + if (param_index >= 0) { + vmm_stat = this->pVmmAPI->setHybPolarity(param_index, value); + if (vmm_stat != vmmSuccess) status = asynError; + goto endOfWriteInt32; + } - for (int hyb = 0; hyb < number_hybrids; hyb++) - setIntegerParam(vmmHybLinkStatus_[hyb], std::stoi(pVmmAPI->checkLinkStatus(hyb))); + endOfWriteInt32: + if (param_index < 0) { + status = asynError; } + setIntegerParam(function, value); + callParamCallbacks(); + return status; + } -asynStatus VMMTbl::writeInt8Array(asynUser *pasynUser, epicsInt8 *value, size_t nElements) -{ +asynStatus VMMTbl::readInt8Array(asynUser *pasynUser, epicsInt8 *value, size_t nElements, size_t *nIn){ - int function, addr; - int ncopy = CHANNELS_PER_VMM; - const char *paramName; - const char *functionName = "writeInt8Array"; - int status = asynSuccess; - std::vector<epicsInt8> int8Array; - Reg pair; + int function, hyb_index, vmm_index, found_param = -10, status = 0; + bool data; + const char* paramName; - status |= parseAsynUser(pasynUser, &function, &addr, ¶mName); + function = pasynUser->reason; getParamName(function, ¶mName); - status |= findRegister(function, &pair); - if (status) { - asynPrint(pasynUser, ASYN_TRACE_ERROR, - "%s:%s: function=%d, name=%s, value=%d. Cannot find which Hybrid-VMM pair is function related to.\n", - driverName, functionName, function, paramName, *value); - return (asynStatus) status; + + if (function < FIRST_VMM_PARAM) return asynPortDriver::readInt8Array(pasynUser, value, nElements, nIn); + + found_param = VecUtils::getIndex(vmmST_, function, hyb_index, vmm_index); + if (found_param == 0) { + for (size_t i = 0; i < nElements; i++) { + status |= (int)this->pVmmAPI->getST(hyb_index, vmm_index, i, data); + value[i] = data; + } + goto endOfReadInt8Array; + } + + endOfReadInt8Array: + if (found_param != 0) { + asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, + "%s:%s: Failed to find paramter %s, index %d.\n", + driverName, __FUNCTION__, paramName, function); + *nIn = 0; + return asynError; } - asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, - "%s:%s: function=%d, name=%s, value=%d, hybrid=%d, vmm=%d, register=%s\n", - driverName, functionName, function, paramName, *value, pair.hyb, pair.vmm, pair.rg.c_str()); + *nIn = nElements; - for (epicsInt8 i = 0; i < ncopy; ++i) { - int8Array.push_back(static_cast<int>(value[i]) >= 1 ? 1 : 0); - pVmmAPI->getHybrid(pair.hyb).getVMM(pair.vmm).setRegister(pair.rg.c_str(), - static_cast<int>(value[i]), - i); + if (status) { + asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, + "%s:%s: Failed to get paramter %s, index %d.\n", + driverName, __FUNCTION__, paramName, function); + return asynError; } - status |= doCallbacksInt8Array(int8Array.data(), int8Array.size(), function, 0); - return (asynStatus) status; + return asynSuccess; } -asynStatus VMMTbl::findRegister(int function, Reg *reg_){ +asynStatus VMMTbl::writeInt8Array(asynUser *pasynUser, epicsInt8 *value, size_t nElements) +{ - int (*array)[VMMS_PER_HYBRID]; - std::map<std::string, int(*)[VMMS_PER_HYBRID]>::iterator it; + int function, hyb_index, vmm_index, status = 0, found_param = -10; + const char* paramName; - it = this->registers.begin(); + function = pasynUser->reason; + getParamName(function, ¶mName); - while ( it != this->registers.end() ){ - std::string reg_name = it->first; - array = registers[reg_name]; + if (function < FIRST_VMM_PARAM) return asynPortDriver::writeInt8Array(pasynUser, value, nElements); - for (int h = 0; h < number_hybrids; h++){ - for (int v = 0; v < VMMS_PER_HYBRID; v++) - { - if (array[h][v] == function){ - reg_->hyb = h; - reg_->vmm = v; - reg_->rg = reg_name; - return asynSuccess; - } - } + found_param = VecUtils::getIndex(vmmST_, function, hyb_index, vmm_index); + if (found_param == 0) { + for (size_t i = 0; i < nElements; i++) { + status |= (int)this->pVmmAPI->setST(hyb_index, vmm_index, i, (bool)value[i]); } - - it++; + goto endOfWriteInt8Array; } - return asynError; + endOfWriteInt8Array: + status |= (int)doCallbacksInt8Array(value, nElements, function, 0); // Comparing different statuses, yes. + if (found_param != 0) { + asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, + "%s:%s: Failed to find paramter %s, index %d.\n", + driverName, __FUNCTION__, paramName, function); + return asynError; + } -} + if (status) { + asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, + "%s:%s: Failed to set paramter %s.\n", + driverName, __FUNCTION__, paramName); + return asynError; + } -asynStatus VMMTbl::writeFloat64(asynUser *pasynUser, epicsFloat64 value) { - asynStatus status = asynSuccess; - int addr = 0; - getAddress(pasynUser, &addr); + return asynSuccess; - return status; } extern "C" { diff --git a/vmmTblApp/src/vmm_tbl.h b/vmmTblApp/src/vmm_tbl.h index 597fd5cdab3fc6288e64433d84546b2f54d2b118..83a573fdc17594afa901cee7740f7ba394b768c8 100644 --- a/vmmTblApp/src/vmm_tbl.h +++ b/vmmTblApp/src/vmm_tbl.h @@ -2,49 +2,65 @@ #include "rmm.h" #include "VMMAPI.h" +#include "Utils.h" -/* Struct to hold Hyb, VMM pair values */ -struct Reg { - int hyb = -1; - int vmm = -1; - std::string rg = "\0"; +/* Struct to hold Hyb, VMM and epics parameter values */ +struct ParamValues { + int param = -1; + std::string value; }; /** Class definition for the VMMTbl class */ class VMMTbl : public asynPortDriver { public: VMMTbl(RMM* rmm, const char *FENPortName, int ring, int node, int hybrids); + + /* Epics parameter management */ asynStatus createEpicsParams(); virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value); - virtual asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value); + // virtual asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value); virtual asynStatus writeInt8Array(asynUser *pasynUser, epicsInt8 *value, size_t nElements); - void setInitialEpicsParams(); - asynStatus findRegister(int function, Reg *reg_); + virtual asynStatus readInt8Array(asynUser *pasynUser, epicsInt8 *value, size_t nElements, size_t *nIn); + virtual asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value); + virtual asynStatus readOctet(asynUser *pasynUser, char *value, size_t maxChars, size_t *nActual, int *eomReason); + asynStatus createParamAndStoreInVector(std::string paramName, asynParamType typ, + std::vector<int>* vectorToStore); protected: + int vmmRegBankVersion; +#define FIRST_VMM_PARAM vmmRegBankVersion int vmmSelectMonitorVMM0_; int vmmSelectMonitorVMM1_; int vmmProcessReadMonitorVMMs_; int vmmMonitorValueVMM0_; int vmmMonitorValueVMM1_; int vmmAcquire_; - int vmmHybFwVersion_[HYBRIDS_PER_FEN]; - int vmmHybId_[HYBRIDS_PER_FEN]; - int vmmHybGeoPos_[HYBRIDS_PER_FEN]; - int vmmHybLinkStatus_[HYBRIDS_PER_FEN]; - //Registers channels per hybrid, per VMM - int vmmST_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID]; - int vmmSL_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID]; - int vmmSC_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID]; - int vmmSTH_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID]; - int vmmSM_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID]; - int vmmSMX_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID]; - std::map<std::string, int(*)[VMMS_PER_HYBRID]> registers{{"st", vmmST_}, {"sc", vmmSC_}, - {"sl", vmmSL_}, {"sth", vmmSTH_}, - {"sm", vmmSM_}, {"smx", vmmSMX_}}; + std::vector<int> vmmHybFwVersion_; + std::vector<int> vmmHybId_; + std::vector<int> vmmHybGeoPos_; + std::vector<int> vmmHybLinkStatus_; + std::vector<int> vmmHybSkew_; + std::vector<int> vmmHybWidth_; + std::vector<int> vmmHybPolarity_; + std::vector<std::vector<int>> vmmSC_; + std::vector<std::vector<int>> vmmSL_; + std::vector<std::vector<int>> vmmST_; + std::vector<std::vector<int>> vmmSTH_; + std::vector<std::vector<int>> vmmSM_; + std::vector<std::vector<int>> vmmSD_; + std::vector<std::vector<int>> vmmSMX_; + // //Registers channels per hybrid, per VMM + // int vmmST_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID]; + // int vmmSL_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID]; + // int vmmSC_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID]; + // int vmmSTH_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID]; + // int vmmSM_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID]; + // int vmmSMX_[HYBRIDS_PER_FEN][VMMS_PER_HYBRID]; + // std::map<std::string, int(*)[VMMS_PER_HYBRID]> registers{{"st", vmmST_}, {"sc", vmmSC_}, + // {"sl", vmmSL_}, {"sth", vmmSTH_}, + // {"sm", vmmSM_}, {"smx", vmmSMX_}}; private: static constexpr const char *driverName = "VMMTbl"; std::shared_ptr<VMMAPI> pVmmAPI; - int number_hybrids; };