diff --git a/otsdaq-mu2e-calorimeter/FEInterfaces/ROCCalorimeterInterface.h b/otsdaq-mu2e-calorimeter/FEInterfaces/ROCCalorimeterInterface.h index 79421d5..5e9359b 100644 --- a/otsdaq-mu2e-calorimeter/FEInterfaces/ROCCalorimeterInterface.h +++ b/otsdaq-mu2e-calorimeter/FEInterfaces/ROCCalorimeterInterface.h @@ -88,6 +88,9 @@ class ROCCalorimeterInterface : public ROCPolarFireCoreInterface { }; + bool hasBoardIdFromSerial() const { return haveBoardIdFromSerial_; } + uint16_t getCachedSerialReg147() const { return cachedSerialReg147_; } + uint16_t getCachedBoardIdFromDB() const { return cachedBoardIdFromDB_; } int GetTemperature(int idchannel); // temperature-- @@ -133,18 +136,18 @@ class ROCCalorimeterInterface : public ROCPolarFireCoreInterface { void SetupForNoiseTaking(unsigned int numberOfsamples); void RMZB_writeAllSiPMbias(float *hv); void EnableDisableLEDs(__ARGS__); - + void FindBoardIDFromSerial(__ARGS__); void ConfigureLink(__ARGS__); void ConfigureLink(std::string conf, std::string confFile, bool hvonoff, bool doCalibration, bool setThresholds, int offset); void CalibrateMZB(__ARGS__); - void CalibrateMZB(int boardid); + void CalibrateMZB(); void ToggleMBBusy(__ARGS__); void ToggleMBBusy(bool busyonoff); void SetADCsThresholds(__ARGS__); - void SetADCsThresholds(int boardid, int offset); + void SetADCsThresholds(int offset); void ReadROCErrorCounter (__ARGS__); void ReadMBRegisters (__ARGS__); @@ -156,7 +159,11 @@ class ROCCalorimeterInterface : public ROCPolarFireCoreInterface { private: - + bool haveBoardIdFromSerial_ = false; + uint16_t cachedSerialReg147_ = 0; + uint16_t cachedBoardIdFromDB_ = 0; + void updateBoardIdFromSerial_(); + static const std::set SPECIAL_BLOCK_READ_ADDRS_; std::set _pin_diode_list; diff --git a/otsdaq-mu2e-calorimeter/FEInterfaces/ROCCalorimeterInterface_interface.cc b/otsdaq-mu2e-calorimeter/FEInterfaces/ROCCalorimeterInterface_interface.cc index bcf977b..cc3b35c 100644 --- a/otsdaq-mu2e-calorimeter/FEInterfaces/ROCCalorimeterInterface_interface.cc +++ b/otsdaq-mu2e-calorimeter/FEInterfaces/ROCCalorimeterInterface_interface.cc @@ -2,6 +2,7 @@ #include "otsdaq-mu2e-calorimeter/FEInterfaces/ROCCalorimeterInterface.h" #include "otsdaq/Macros/InterfacePluginMacros.h" +#include "otsdaq/ConfigurationInterface/ConfigurationManager.h" #include "cetlib/filepath_maker.h" @@ -87,6 +88,12 @@ ROCCalorimeterInterface::ROCCalorimeterInterface(const std::string& rocUID, cons std::vector{}, // output parameters 1); +registerFEMacroFunction("Find BoardID From Serial", + static_cast(&ROCCalorimeterInterface::FindBoardIDFromSerial), + std::vector{}, // input + std::vector{"Status"}, // output + 1); + registerFEMacroFunction("Set Board Voltages", static_cast(&ROCCalorimeterInterface::SetBoardVoltages), std::vector{"configuration folder, Default:= nominal", @@ -113,13 +120,13 @@ ROCCalorimeterInterface::ROCCalorimeterInterface(const std::string& rocUID, cons registerFEMacroFunction("Calibrate Mzb", static_cast(&ROCCalorimeterInterface::CalibrateMZB), - std::vector{"BoardID, Default := -1]"}, // inputs parameters + std::vector{}, // inputs parameters std::vector{}, // output parameters 1); // requiredUserPermissions registerFEMacroFunction("SetADCsThresholds", static_cast(&ROCCalorimeterInterface::SetADCsThresholds), - std::vector{"BoardID, Default := -1]", "Offset, Default := 0]"}, // inputs parameters + std::vector{"Offset, Default := 0]"}, // inputs parameters std::vector{}, // output parameters 1); // requiredUserPermissions @@ -281,36 +288,25 @@ void ROCCalorimeterInterface::universalBlockRead(char* address, char* returnValu void ROCCalorimeterInterface::ROCSlowControl(__ARGS__) { std::stringstream os; - DTCLib::roc_address_t address = 147; - DTCLib::roc_data_t readVal; - readVal = readRegister(address); - - std::string confFile = "boardMap.config"; - cet::filepath_lookup lookup_policy("MU2E_CALORIMETER_CONFIG_PATH"); - auto filename = lookup_policy(confFile); + const int boardID = static_cast(cachedBoardIdFromDB_); + __COUT_INFO__ << "Target BoardID = " << boardID << __E__; - std::ifstream confMap(filename); - if(!confMap.is_open()) { - __FE_SS__ << "Could not open file: " << filename << __E__; + if(!cachedBoardIdFromDB_) + { + __FE_SS__ << "Skipping tag slow control for board " << boardID + << ", boardID not initialized correctly!" << __E__; __FE_SS_THROW__; - ; - } - - int boardid = -1; + return; + } - for(int iboard = 0; iboard < 161; iboard++) { - int nboard; - int notused; - int buid; - - confMap >> nboard >> notused >> buid; - if(readVal == buid) { - boardid = nboard; - break; - } - } - confMap.close(); + if(boardID >= 160) + { + __FE_SS__ << "Skipping upload MZB parameters to board " << boardID + << ", boardID out of range!" << __E__; + __FE_SS_THROW__; + return; + } const char* env_path = std::getenv("MU2E_CALORIMETER_CONFIG_PATH"); if(!env_path) { @@ -335,7 +331,7 @@ void ROCCalorimeterInterface::ROCSlowControl(__ARGS__) { } char filename_buff[50]; - std::snprintf(filename_buff, sizeof(filename_buff), "slowControl%03d.log", boardid); + std::snprintf(filename_buff, sizeof(filename_buff), "slowControl%03d.log", boardID); fs::path output_file = slow_control_dir / filename_buff; std::ofstream file(output_file, std::ios::app); @@ -350,7 +346,7 @@ void ROCCalorimeterInterface::ROCSlowControl(__ARGS__) { std::string timestamp = std::ctime(&now_c); timestamp.pop_back(); - file << "[" << timestamp << "] " << boardid << " "; + file << "[" << timestamp << "] " << boardID << " "; os << __E__; @@ -717,6 +713,114 @@ void ROCCalorimeterInterface::readROCBlock(std::vector& data //================================================================================================== + + void ots::ROCCalorimeterInterface::FindBoardIDFromSerial(__ARGS__) +{ + std::stringstream os; + + // updateBoardIdFromSerial_(); + + + os << "haveBoardIdFromSerial_ = " << (haveBoardIdFromSerial_ ? "true" : "false") << "\n"; + os << "cachedSerialReg147_ = 0x" << std::hex << cachedSerialReg147_ << std::dec << "\n"; + os << "cachedBoardIdFromDB_ = " << cachedBoardIdFromDB_ << "\n"; + + const int boardID = static_cast(cachedBoardIdFromDB_); + os << "Target BoardID = " << boardID << "\n"; + + const ots::ConfigurationManager* cfgMgr = getConfigurationManager(); + + if(boardID >= 160) { + os << "Skipping setting thresholds to board " << boardID << ", boardID out of range!" << __E__; + __SET_ARG_OUT__("Status", os.str()); + return; + } + + auto rows = cfgMgr->getNode("SubsystemCalorimeterThresholdsTable").getChildren(); + os << "SubsystemCalorimeterThresholdsTable rows=" << rows.size() << "\n"; + + const ots::ConfigurationTree* rec = nullptr; + std::string recUID; + + for(const auto& row : rows) + { + const auto& r = row.second; + const uint64_t tableBoardId = r.getNode("BoardID").getValue(); + + if(static_cast(tableBoardId) != boardID) + continue; + + rec = &r; + recUID = row.first; + break; + } + + if(!rec) + { + os << "ERROR: BoardID=" << boardID << " not found in SubsystemCalorimeterThresholdsTable\n"; + __SET_ARG_OUT__("Status", os.str()); + return; + } + + os << "FOUND record UID=" << recUID << " for BoardID=" << boardID << "\n"; + + auto thrBmp = rec->getNode("Thresholds").getValueAsBitMap(); + os << "Thresholds bitmap: rows=" << thrBmp.numberOfRows() + << " cols(0)=" << thrBmp.numberOfColumns(0) << "\n"; + + const uint32_t thrCols = thrBmp.numberOfColumns(0); + const uint32_t thrToPrint = std::min(thrCols, 20); + for(uint32_t ch = 0; ch < thrToPrint; ++ch) + { + std::string v = thrBmp.get(0, ch); + if(v.empty()) v = "0"; + os << "Thr[" << ch << "]=" << v << "\n"; + } + + + __SET_ARG_OUT__("Status", os.str()); +} + + + + +/////////////////////// + +void ROCCalorimeterInterface::updateBoardIdFromSerial_() +{ + haveBoardIdFromSerial_ = false; + cachedSerialReg147_ = 0; + cachedBoardIdFromDB_ = 0; + + cachedSerialReg147_ = readRegister(147); + + const ots::ConfigurationManager* cfgMgr = getConfigurationManager(); + + auto rows = cfgMgr->getNode("SubsystemCalorimeterParametersTable").getChildren(); + for(const auto& row : rows) + { + const auto& rec = row.second; + const uint64_t tableSerial = rec.getNode("SerialNumber").getValue(); + + if(static_cast(tableSerial) != cachedSerialReg147_) + continue; + + cachedBoardIdFromDB_ = static_cast(rec.getNode("BoardId").getValue()); + writeRegister(ROC_ADDRESS_BOARD_ID, cachedBoardIdFromDB_); + haveBoardIdFromSerial_ = true; + break; + } + + if(haveBoardIdFromSerial_) + __FE_COUT__ << "Mapped serial 0x" << std::hex << cachedSerialReg147_ << std::dec + << " -> BoardId=" << cachedBoardIdFromDB_ << __E__; + else + __FE_COUT__ << "No match in ParametersTable for serial 0x" + << std::hex << cachedSerialReg147_ << std::dec << __E__; + +} + + /* //================================================================================================== @@ -800,11 +904,10 @@ void ROCCalorimeterInterface::configure(void) try { else __COUT_INFO__ << "Configuration failed! :(" << __E__; - // int myTemp = GetTemperature(1); - // __COUTV__(myTemp); - // __COUT__<<"my temp"<(cachedBoardIdFromDB_); + __COUT_INFO__ << "Target BoardID = " << boardID << __E__; - cet::filepath_lookup lookup_policy("MU2E_CALORIMETER_CONFIG_PATH"); - auto filename = lookup_policy(confFile); - std::ifstream confMap(filename); - if(!confMap.is_open()) { - __FE_SS__ << "Could not open file: " << filename << __E__; - __FE_SS_THROW__; - ; - } + if(!cachedBoardIdFromDB_) + { + updateBoardIdFromSerial_(); + if(!cachedBoardIdFromDB_){ - int boardid = -1; - - for(int iboard = 0; iboard < 161; iboard++) { - int nboard; - int notused; - int buid; - - confMap >> nboard >> notused >> buid; - if(readVal == buid) { - boardid = nboard; - break; + __FE_SS__ << "Skipping configuring board " << boardID + << ", boardID not initialized correctly!" << __E__; + __FE_SS_THROW__; + return; } - } - confMap.close(); - - if(boardid != -1) { - if(doCalibration) - CalibrateMZB(boardid); - SetBoardVoltages(hvonoff, boardid, conf); // This checks which channels are pin diodes - if(setThresholds) - SetADCsThresholds(boardid, offset); - writeRegister(ROC_ADDRESS_BOARD_ID, boardid); - } else { - __FE_SS__ << "Cannot match board unique ID: readval is " << readVal << ", while boardid is " << boardid << __E__; - __FE_SS_THROW__; - ; - } + } + + if(boardID >= 160) + { + __FE_SS__ << "Skipping configuring board " << boardID + << ", boardID out of range!" << __E__; + __FE_SS_THROW__; + return; + } + + if(doCalibration) + CalibrateMZB(); + SetBoardVoltages(hvonoff, boardID, conf); // This checks which channels are pin diodes + if(setThresholds) + SetADCsThresholds(offset); } // end ConfigureLink() @@ -1101,9 +1193,8 @@ void ROCCalorimeterInterface::ConfigureLink(std::string conf, std::string confFi //================================================================================================== void ROCCalorimeterInterface::CalibrateMZB(__ARGS__) { - int boardID = __GET_ARG_IN__("BoardID, Default := -1]", int, -1); - CalibrateMZB(boardID); + CalibrateMZB(); } // end ConfigureLink() @@ -1111,8 +1202,29 @@ void ROCCalorimeterInterface::CalibrateMZB(__ARGS__) { //================================================================================================== -void ROCCalorimeterInterface::CalibrateMZB(int boardID) { +void ROCCalorimeterInterface::CalibrateMZB() { + char buff[50]; + + const int boardID = static_cast(cachedBoardIdFromDB_); + __COUT_INFO__ << "Target BoardID = " << boardID << __E__; + + if(!cachedBoardIdFromDB_) + { + __FE_SS__ << "Skipping upload MZB parameters to board " << boardID + << ", boardID not initialized correctly!" << __E__; + __FE_SS_THROW__; + return; + } + + if(boardID >= 160) + { + __FE_SS__ << "Skipping upload MZB parameters to board " << boardID + << ", boardID out of range!" << __E__; + __FE_SS_THROW__; + return; + } + sprintf(buff, "mzb%03d.config", boardID); cet::filepath_lookup lookup_policy("MU2E_CALORIMETER_CONFIG_PATH"); @@ -1122,7 +1234,6 @@ void ROCCalorimeterInterface::CalibrateMZB(int boardID) { if(!confFile.is_open()) { __FE_SS__ << "Could not open file: " << filename << __E__; __FE_SS_THROW__; - ; } __COUT_INFO__ << "Opening file: " << filename << __E__; @@ -1161,13 +1272,113 @@ void ROCCalorimeterInterface::CalibrateMZB(int boardID) { //================================================================================================== void ROCCalorimeterInterface::SetADCsThresholds(__ARGS__) { - int boardID = __GET_ARG_IN__("BoardID, Default := -1]", int, -1); - int offset = __GET_ARG_IN__("offset, Default := 0]", int, 0); + int offset = __GET_ARG_IN__("Offset, Default := 0]", int, 0); - SetADCsThresholds(boardID, offset); + SetADCsThresholds(offset); } // end ConfigureLink() -void ROCCalorimeterInterface::SetADCsThresholds(int boardID, int offset) { + +void ROCCalorimeterInterface::SetADCsThresholds(int offset) +{ + + const int boardID = static_cast(cachedBoardIdFromDB_); + __COUT_INFO__ << "Target BoardID = " << boardID << __E__; + + if(boardID >= 160) + { + __COUT_ERR__ << "Skipping setting thresholds to board " << boardID + << ", boardID out of range!" << __E__; + return; + } + + if(!cachedBoardIdFromDB_) + { + __COUT_ERR__ << "Skipping setting thresholds to board " << boardID + << ", boardID not initialized correctly!" << __E__; + return; + } + + const ots::ConfigurationManager* cfgMgr = getConfigurationManager(); + if(!cfgMgr) + { + __COUT_ERR__ << "ERROR: getConfigurationManager() returned nullptr" << __E__; + return; + } + + auto rows = cfgMgr->getNode("SubsystemCalorimeterThresholdsTable").getChildren(); + const ots::ConfigurationTree* rec = nullptr; + std::string recUID; + + for(const auto& row : rows) + { + const auto& r = row.second; + const uint64_t tableBoardId = r.getNode("BoardID").getValue(); + if(static_cast(tableBoardId) != boardID) + continue; + rec = &r; + recUID = row.first; + break; + } + + if(!rec) + { + __COUT_ERR__ << "ERROR: BoardID=" << boardID + << " not found in SubsystemCalorimeterThresholdsTable. " + << "Setting default thresholds=2300 for 20 channels." << __E__; + + for(int ichan = 0; ichan < 20; ++ichan) + writeRegister(ROC_ADDRESS_BASE_THRESHOLD + ichan, 2300); + return; + } + + __COUT_INFO__ << "FOUND record UID=" << recUID << " for BoardID=" << boardID << __E__; + + auto thrBmp = rec->getNode("Thresholds").getValueAsBitMap(); + for(int ichan = 0; ichan < 20; ++ichan) + { + int thr = 2300; + if(thrBmp.numberOfRows() > 0 && thrBmp.numberOfColumns(0) > static_cast(ichan)) + { + std::string s = thrBmp.get(0, ichan); + if(!s.empty()) + { + char* endp = nullptr; + double v = std::strtod(s.c_str(), &endp); + if(endp != s.c_str()) + thr = static_cast(v + (v >= 0 ? 0.5 : -0.5)); + } + } + + int thr2set = thr + offset; + + for(auto pin : _pin_diode_list) + { + if(boardID * 100 + ichan == pin) + { + thr2set = thr; + __COUT_INFO__ << "Board " << boardID << " Channel " << ichan + << " detected as pin diode. Ignoring requested offset. " + << "Threshold: " << thr2set << __E__; + break; + } + } + + __COUT_INFO__ << "Board " << boardID << " ch " << ichan + << " thr=" << thr << " offset=" << offset + << " -> set " << thr2set << __E__; + + writeRegister(ROC_ADDRESS_BASE_THRESHOLD + ichan, thr2set); + } + + __COUT_INFO__ << "Thresholds set done from SubsystemCalorimeterThresholdsTable (UID=" + << recUID << ") for boardID=" << boardID << __E__; +} + + + + + +/*void ROCCalorimeterInterface::SetADCsThresholds(int boardID, int offset) { char buff[50]; sprintf(buff, "dirac%03d.baseline", boardID); @@ -1220,7 +1431,7 @@ void ROCCalorimeterInterface::SetADCsThresholds(int boardID, int offset) { __COUT_INFO__ << "Thresholds set done.." << filename << __E__; -} // end SetADCsThresholds() +} // end SetADCsThresholds()*/ //==================================================================================================