#include "TPCCommandCoderDBcache.h" #define CoCoVersion "TPCCommandCoderDBcache" //=========================================================================== TPCCommandCoderDBcache::TPCCommandCoderDBcache() { // // Constructor: Setup and connect to DB // string tempstring; // Switch to write config output also to file. Will be ignored for tag = 0 (RECONFIGURE) fFile = true; #ifdef P2 fdbSystem = 0; // 0 = Oracle@P2 fDebugFileName = "/home/tpc/configs/TPCCommandCoderDBcache.log"; fOutputFilePath = "/home/tpc/configs/"; fOneSideOnly = true; // 2 JICLs are used for the 2 TPC sides #else fdbSystem = 2; // 1 = Oracle@DCSlab; 2 = Oracle test (devdb10). fDebugFileName = "/tmp/TPCCommandCoderDBcache.log"; fOutputFilePath = "/tmp/"; fOneSideOnly = false; // 1 JICL used for full TPC (lab setup) #endif char desc[256]; fALTRO = new AltroCommandCoder(); fBC = new BoardControllerCommandCoder(); fRCU = new RCUCommandCoder(); fRCUce = new RCUControlEngine(); fDBfp = new FERODBFieldPositions(); fDB = new OracleDB(); for (int32_t ii=0; ii<216; ii++) { fReadoutList[ii] = new ReadoutList(); fAFL[ii] = new Afl(); fDataBlock[ii] = new RcuContainer(); fRCUon[ii] = false; } fDBqc = NULL; // Class to handle queries fConfigTCparam = true; // Fast configuration writes only non-zero values fFirstCall = true; // CoCo was called first time fLastCallTime = 0; fError.clear(); fwatchDogTimeout = 120; fLogger = Logger::getInstance(); fLogger->setlogfilename(fDebugFileName.c_str()); fLogger->setDebugLevel(1); fLogger->append("======================================="); fLogger->appendTime(); fLogger->append("TPCCommandCoderDBcache constructor called."); #ifdef TPC_REVISION string revision(TPC_REVISION); fVersion = CoCoVersion; fVersion.append(" (Revision "); fVersion.append(revision); fVersion.append(")"); tempstring="Version: "+fVersion; fLogger->append(tempstring.c_str()); #else fVersion = CoCoVersion; fLogger->appendWarning("Warning: TPC_REVISION not defined"); #endif sprintf(desc, "Watchdog Timeout set to %ds", fwatchDogTimeout); fLogger->append(desc); // Open DB connection switch (fdbSystem) { case 0 : fDBqc = new DBQueryCreator(); fDB = new OracleDB(); pdbUser = "tpcfero"; pdbPassword = "tpc1234"; pdbConnectString = "alice_fero"; try { fDB->connect(pdbUser, pdbPassword, pdbConnectString); } catch(SQLException& exception) { sprintf(desc, "%s (%s)", exception.what(), pdbConnectString.c_str()); fLogger->appendError(desc); fError.push_back(desc); } break; case 1 : fDBqc = new DBQueryCreator(); fDB = new OracleDB(); pdbUser = "tpccfg"; pdbPassword = "tpc"; pdbConnectString = "aldcs031"; try { fDB->connect(pdbUser, pdbPassword, pdbConnectString); } catch(SQLException& exception) { sprintf(desc, "%s (%s)", exception.what(), pdbConnectString.c_str()); fLogger->appendError(desc); fError.push_back(desc); } break; case 2 : fDBqc = new DBQueryCreator(); fDB = new OracleDB(); pdbUser = "alice_dcs_tpc"; pdbPassword = "alice.123"; pdbConnectString = "devdb10"; try { fDB->connect(pdbUser, pdbPassword, pdbConnectString); } catch(SQLException& exception) { sprintf(desc, "%s (%s)", exception.what(), pdbConnectString.c_str()); fLogger->appendError(desc); fError.push_back(desc); } break; default: sprintf(desc, "Error. Wrong DB system."); fLogger->appendError(desc); fError.push_back(desc); break; } // end switch if ( isConnected() ) { tempstring = "Successfully connected to DB "+pdbConnectString; fLogger->append(tempstring.c_str()); fLogger->append( "======================================="); } } //=========================================================================== TPCCommandCoderDBcache::~TPCCommandCoderDBcache() { // // Destructor. Close DB connection. // char desc[256]; try { fDB->disconnect(); } catch(SQLException& exception) { fLogger->appendTime(); fLogger->append(exception.what()); strncpy(desc, exception.what(), 255); fError.push_back(desc); } // Close config output file if (fFile) { if (fOfsAltro) delete fOfsAltro; if (fOfsRcu) delete fOfsRcu; } delete fDB; delete fDBqc; delete fDBfp; delete fRCU; delete fALTRO; delete fBC; delete fRCUce; for ( int32_t ii=0; ii<216; ii++) { delete fReadoutList[ii]; delete fDataBlock[ii]; delete fAFL[ii]; } } //=========================================================================== void TPCCommandCoderDBcache::reset() { // // Reset most things, keep data // for (int32_t ii=0; ii<216; ii++) { fRCUon[ii] = false; } try { for ( int32_t ii=0; ii<216; ii++) { fReadoutList[ii]->reset(); fDataBlock[ii]->reset(); fAFL[ii]->reset(); } } catch(TpcException& exception) { fLogger->appendTime(); fLogger->append(exception.what()); char desc[256]; strncpy(desc, exception.what(), 255); fError.push_back(desc); } } //=========================================================================== uint32_t* TPCCommandCoderDBcache::getDataBlock() { // // Send the data block // return fDataBlock[fTarget]->getDataBlock(); } //=========================================================================== int32_t TPCCommandCoderDBcache::createDataBlocks(int tag){ // // Create all data blocks. // // If tag==0, a short block is assembled in order to have the FeeServer reset the // FEE and reconfigure using locally stored data on the DCS boards. // // If tag is a positive number, the DB is contacted in order to get the configuration // data. The DB values should be such that the TPC FEE starts acquiring data upon arrival // of a L1 trigger. // // If tag is a negative number, the difference is that the relevant values from the DB // are modified by the command coder such that the TPC FEE starts acquiring data upon // arrival of a L0 trigger. // char desc[256]; string tempstring; if ( !isConnected() ) { sprintf(desc, "*Error: Not connected to db %s!", pdbConnectString.c_str()); fLogger->appendTime(); fLogger->appendError(desc); fError.push_back(desc); return -1; // Error } fLogger->append(""); fLogger->append( "======================================="); fLogger->appendTime(); tempstring="*Querying DB in order to get all configuration data"; fLogger->append(tempstring.c_str()); tempstring = "Query="+fDBqc->getSqlBindSelectAllPartitionConfigData(); fLogger->appendInfo(tempstring.c_str()); reset(); Mapping pm; // The mapping of hardware adresses to pads int32_t side; // 0, 1; int32_t sector; // 0 - 17 int32_t rcu; // 0 - 5 int32_t roc; // 0 - 71 int32_t branch; // 0, 1 int32_t fec; // 0 ... 8, 9, 11 or 12 int32_t altro; // 0 ... 7 uint64_t data = 0; int32_t rcuID = 0; uint32_t cstb_delay = 0; uint32_t clk_ratio = 0; uint32_t nsam_ev = 0; uint32_t trg_mode = 0; uint32_t dis_rdyrx = 0; uint32_t chan_skip = 0; uint32_t sparse_rdo = 0; uint32_t meb_mode = 0; uint32_t l1_latency = 0; uint32_t l1_window = 0; uint32_t l1_msg_lat_min = 0; uint32_t l1_msg_lat_max = 0; uint32_t l2_lat_min = 0; uint32_t l2_lat_max = 0; uint32_t roi_lat_min = 0; uint32_t roi_lat_max = 0; uint32_t roi_conf1 = 0; uint32_t roi_conf2 = 0; uint32_t cdh_version = 0; uint32_t zs_cfg = 0; uint32_t bc2_cfg = 0; uint32_t bc1_cfg = 0; uint32_t pwsv = 0; uint32_t flt_en = 0; uint32_t nbuf = 0; uint32_t ptrg = 0; uint64_t fPed = 0; uint64_t zsThr = 0; uint64_t aqStart = 0; uint64_t aqStop = 0; uint64_t k1 = 0; uint64_t k2 = 0; uint64_t k3 = 0; uint64_t l1 = 0; uint64_t l2 = 0; uint64_t l3 = 0; const uint32_t maxtb = 1008; // Trigger offset: Start acquisition at L0 or L1 int32_t trigger_offset = 0; if ( tag < 0 ) { trg_mode = 1; tag = abs(tag); } try { fDB->createTransaction(); if (fOneSideOnly) { sprintf(desc, "*Query data for 1 TPC side only."); fLogger->appendInfo(desc); fDB->setSQLgetRowCount(fDBqc->getSqlBindSelectSidePartitionConfigData()); fDB->setNumber(0, tag); fDB->setNumber(1, fSide); } else { sprintf(desc, "*Query data for 2 TPC sides."); fLogger->appendInfo(desc); fDB->setSQLgetRowCount(fDBqc->getSqlBindSelectAllPartitionConfigData()); fDB->setNumber(0, tag); } fDB->executeQuery(); fDB->getRow(); int32_t rowcount = fDB->getRowValueAsInt(0); if ( rowcount < 1 ) { tempstring="*Got no rows with configuration data."; fLogger->appendTime(); fLogger->appendError(tempstring.c_str()); fError.push_back(tempstring.c_str()); return -1; // Error } sprintf(desc, "*AllPartitionConfigData query returned %d rows.", rowcount); fLogger->append(desc); fLogger->append( "======================================="); //fDB->deleteTransaction(); //fDB->createTransaction(); if (fOneSideOnly) { fDB->setSQL(fDBqc->getSqlBindSelectSidePartitionConfigData()); fDB->setNumber(0, tag); fDB->setNumber(1, fSide); } else { fDB->setSQL(fDBqc->getSqlBindSelectAllPartitionConfigData()); fDB->setNumber(0, tag); } fDB->executeQuery(); int32_t lastRcu = -1; bool newRcu = true; if ( fFile ) { fOfsRcu = new ofstream(); // Configuration data file for offline fOfsAltro = new ofstream(); // Configuration data file for offline } else { fOfsRcu = NULL; fOfsAltro = NULL; } // ====================================================================== // Go through the rows (ALTROs). Start filling Data Buffers // ====================================================================== for ( int32_t rowCounter = 0; rowCounter < rowcount; rowCounter++ ) { //for ( int32_t rowCounter = 0; rowCounter < 1; rowCounter++ ) { // HACK! fDB->getRow(); side = fDB->getRowValueAsInt(fDBfp->QAll_Sec_SidePosition); sector = fDB->getRowValueAsInt(fDBfp->QAll_Sec_Position); rcu = fDB->getRowValueAsInt(fDBfp->QAll_Rcu_Position); roc = pm.GetRocFromPatch(side, sector, rcu); branch = fDB->getRowValueAsInt(fDBfp->QAll_Fec_BranchPosition); fec = fDB->getRowValueAsInt(fDBfp->QAll_Fec_Position); altro = fDB->getRowValueAsInt(fDBfp->QAll_Altro_Position); // Target number (rcu=0...215) int32_t target = side*6*18+sector*6+rcu; if ( target != lastRcu ) { newRcu = true; lastRcu = target; fLogger->append(""); sprintf(desc, "===== TPC-FEE_%d_%02d_%d =====", side, sector, rcu); fLogger->append(desc); fLogger->appendTime(); tempstring="*Assembling configure command block from DB"; fLogger->append(tempstring.c_str()); } else { newRcu = false; } // Debug output sprintf(desc, "Next row! Roc=%d, Side=%d, Sector=%d, Rcu=%d, Branch=%d, fec=%d, altro=%d", roc, side, sector, rcu, branch, fec, altro); fLogger->appendInfo(desc); // Debug output for ( int32_t fieldCounter = 0; fieldCounter < fDB->getFieldCount(); fieldCounter++ ) { tempstring = fDB->getRowValueAsString(fieldCounter); sprintf(desc,"Column %d -> %s", fieldCounter, tempstring.c_str()); fLogger->appendDebug(desc); } if ( newRcu ) { // This is the first ALTRO of a new RCU fReadoutList[target]->reset(); // reset readout list memory container fAFL[target]->reset(); // reset active frontend list container // Open output files sprintf(desc, "TPC-FEE_%d_%02d_%d", side, sector, rcu); // RCU file if ( fOfsRcu->is_open() ) fOfsRcu->close(); fOutputFileNameRcu = fOutputFilePath+"RCUconfig_"+desc+".data"; fOfsRcu->open(fOutputFileNameRcu.c_str(), ios::out); *fOfsRcu << 98 << endl; // Altro file if ( fOfsAltro->is_open() ) fOfsAltro->close(); fOutputFileNameAltro = fOutputFilePath+"ALTROconfig_"+desc+".data"; fOfsAltro->open(fOutputFileNameAltro.c_str(), ios::out); *fOfsAltro << 99 << endl; // ======================================================= // ================ Prepare Data Buffer ================== // ======================================================= // DCS configuration only fDataBlock[target]->setExternalConfiguration(false); // Store data on DCS board; execute locally saved instructions fDataBlock[target]->setConfigurePhysics1(); // Set RCU ID in configuration block fDataBlock[target]->setHardwareAddress(target); // ======================================================= // ================= Fill Rcu registers ================== // ======================================================= rcuID = fDB->getRowValueAsInt(fDBfp->QAll_Rcu_id); fRCUon[target] = (bool)fDB->getRowValueAsInt(fDBfp->QAll_Rcu_ON_RCU); // Some registers for RCU Fw V2 nsam_ev = (uint32_t)fDB->getRowValueAsInt(fDBfp->QAll_Rcu_ALTROIF_NSAM_EV); clk_ratio = (uint32_t)fDB->getRowValueAsInt(fDBfp->QAll_Rcu_ALTROIF_CLK_RATIO); cstb_delay = (uint32_t)fDB->getRowValueAsInt(fDBfp->QAll_Rcu_ALTROIF_CSTB_DELAY); chan_skip = (uint32_t)fDB->getRowValueAsInt(fDBfp->QAll_Rcu_RDOMOD_SKIP_EMPTY); sparse_rdo = (uint32_t)fDB->getRowValueAsInt(fDBfp->QAll_Rcu_RDOMOD_SPARSE_RDO); meb_mode = (uint32_t)fDB->getRowValueAsInt(fDBfp->QAll_Rcu_RDOMOD_MEB_MODE); dis_rdyrx = (uint32_t)fDB->getRowValueAsInt(fDBfp->QAll_Rcu_RDOMOD_DISABLE_RDYRX); cdh_version = (uint32_t)fDB->getRowValueAsInt(fDBfp->QAll_Rcu_TTC_CONTROL_CDH_VERSION); l1_latency = (uint32_t)fDB->getRowValueAsInt(fDBfp->QAll_Rcu_TTC_L1_LATENCY); l1_window = (uint32_t)fDB->getRowValueAsInt(fDBfp->QAll_Rcu_TTC_L1_LATENCY_WINDOW); l1_msg_lat_min = (uint32_t)fDB->getRowValueAsInt(fDBfp->QAll_Rcu_TTC_L1_MSG_LATENCY_MIN); l1_msg_lat_max = (uint32_t)fDB->getRowValueAsInt(fDBfp->QAll_Rcu_TTC_L1_MSG_LATENCY_MAX); l2_lat_min = (uint32_t)fDB->getRowValueAsInt(fDBfp->QAll_Rcu_TTC_L2_LATENCY_MIN); l2_lat_max = (uint32_t)fDB->getRowValueAsInt(fDBfp->QAll_Rcu_TTC_L2_LATENCY_MAX); roi_lat_min = (uint32_t)fDB->getRowValueAsInt(fDBfp->QAll_Rcu_TTC_ROI_LATENCY_MIN); roi_lat_max = (uint32_t)fDB->getRowValueAsInt(fDBfp->QAll_Rcu_TTC_ROI_LATENCY_MAX); roi_conf1 = (uint32_t)fDB->getRowValueAsInt(fDBfp->QAll_Rcu_TTC_ROI_CONFIG1); roi_conf2 = (uint32_t)fDB->getRowValueAsInt(fDBfp->QAll_Rcu_TTC_ROI_CONFIG1); // If tag was negative, the ALTROs are to be started at L0 if ( trg_mode == 1 ) { trigger_offset = l1_latency/(1<<(1+clk_ratio)); // offset in number of time bins nsam_ev += trigger_offset; if (nsam_ev > maxtb) nsam_ev = maxtb; } if ( !fRCUon[target] ){ sprintf(desc, "*RCU off"); fLogger->append(desc); if ( fFile && (tag != 0) ) { *fOfsRcu << pm.GetDDLfromPatch(side, sector, rcu) << " " << fRCUon[target] << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << endl; } } else { sprintf(desc, "*RCU_ID=%d: tag=%d | chan_skip=%d | sparse_rdo=%d | clk_ratio=%d", rcuID, tag, chan_skip, sparse_rdo, clk_ratio); fLogger->append(desc); sprintf(desc, "*ALTROs are started at L%d", abs((int)(trg_mode-1))); fLogger->append(desc); if ( fFile && (tag != 0) ) { *fOfsRcu << pm.GetDDLfromPatch(side, sector, rcu) << " " << fRCUon[target] << " " << nsam_ev << " " << clk_ratio << " " << cstb_delay << " " << (sparse_rdo|chan_skip) << " " << meb_mode << " " << dis_rdyrx << " " << cdh_version << " " << l1_latency << " " << l1_window << " " << l1_msg_lat_min << " " << l1_msg_lat_max << " " << l2_lat_min << " " << l2_lat_max << " " << roi_conf1 << " " << roi_conf2 << " " << roi_lat_min << " " << roi_lat_max << " " << trg_mode << endl; } } if ( fRCUon[target] ) { // Fill RCU registers for RCU Fw V2 // TRGCONF Register fDataBlock[target]->fillRcu((uint32_t)fRCUce->sendRCU_WRITE_TRGCFG(), false); fDataBlock[target]->fillRcu((uint32_t)fRCU->codeTRGCONF(trg_mode)); // ALTROIF Register fDataBlock[target]->fillRcu((uint32_t)fRCUce->sendRCU_WRITE_ALTROIF(), false); fDataBlock[target]->fillRcu((uint32_t)fRCU->codeALTROIF(cstb_delay, clk_ratio, nsam_ev)); // RDOMOD Register fDataBlock[target]->fillRcu((uint32_t)fRCUce->sendRCU_WRITE_RDOMOD(), false); fDataBlock[target]->fillRcu((uint32_t)fRCU->codeRDOMOD(chan_skip, sparse_rdo, meb_mode)); // TTC_L1_LATENCY Register fDataBlock[target]->fillRcu((uint32_t)fRCUce->sendRCU_WRITE_TTC_L1_LATENCY(), false); fDataBlock[target]->fillRcu((uint32_t)fRCU->codeTTC_L1_LATENCY(l1_latency, l1_window)); // TTC_L1_MSG_LATENCY Register fDataBlock[target]->fillRcu((uint32_t)fRCUce->sendRCU_WRITE_TTC_L1_MSG_LATENCY(), false); fDataBlock[target]->fillRcu((uint32_t)fRCU->codeTTC_L1_MSG_LATENCY(l1_msg_lat_min, l1_msg_lat_max)); // TTC_L2_LATENCY Register fDataBlock[target]->fillRcu((uint32_t)fRCUce->sendRCU_WRITE_TTC_L2_LATENCY(), false); fDataBlock[target]->fillRcu((uint32_t)fRCU->codeTTC_L2_LATENCY(l2_lat_min, l2_lat_max)); // TTC_COMMAND Register // CDH v2 is ised by default in RCU Fw V2 //fDataBlock[target]->fillRcu((uint32_t)fRCUce->sendRCU_WRITE_TTC_CONTROL(), false); //fDataBlock[target]->fillRcu((uint32_t)fRCU->codeTTC_CONTROL(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, cdh_version)); // Content of ALTROCFG1/2 registers for RCU Fw V2. We use the value found in the first ALTRO // and assume that all ALTROs have the same configuration for this tag zs_cfg = fALTRO->codeZS_CFG(fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCFG_ZS_GF), fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCFG_ZS_PRE), fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCFG_ZS_POST), fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCFG_ZS_EN)); bc2_cfg = fALTRO->codeBC2_CFG(fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCFG_BC2_PRE), fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCFG_BC2_POST), fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCFG_BC2_PRE)); bc1_cfg = fALTRO->codeBC1_CFG(fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCFG_BC1_MODE), fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCFG_BC1_POL)); pwsv = fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCF2_PWSV); flt_en = fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCF2_FLT_EN); nbuf = fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCF2_BUF); ptrg = fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCF2_PTRG); // ALTROCFG1 Register fDataBlock[target]->fillRcu((uint32_t)fRCUce->sendRCU_WRITE_ALTROCFG1(), false); fDataBlock[target]->fillRcu((uint32_t)fRCU->codeALTROCFG1(zs_cfg, bc2_cfg, bc1_cfg)); // ALTROCFG2 Register fDataBlock[target]->fillRcu((uint32_t)fRCUce->sendRCU_WRITE_ALTROCFG2(), false); fDataBlock[target]->fillRcu((uint32_t)fRCU->codeALTROCFG2(pwsv, flt_en, nbuf, ptrg)); // RCU_ID Register fDataBlock[target]->fillRcu((uint32_t)fRCUce->sendRCU_WRITE_RCUID(), false); fDataBlock[target]->fillRcu((uint32_t)fRCU->codeRCUID(side, sector, rcu)); // Hit List Memory. Is usually configured by FEC Board Controllers when in sparse // readout mode. But needs to be reinitalized in case we want full readout ... if (!(sparse_rdo|chan_skip)) { fDataBlock[target]->fillRcu((uint32_t)fRCUce->sendRCU_WRITE_HLMEM(128), false); for ( uint32_t i = 0; i < 128; i++ ) fDataBlock[target]->fillRcu((uint32_t)0xffffffff, false); // payload, no tailer fDataBlock[target]->fillRcu((uint32_t)fRCUce->sendCE_CMD_TAILER(), false); // tailer } } // end if ( fRCUon[target] ) } // end if ( newRcu ) // ======================================================= // ================= Fill ALTRO registers ================ // ======================================================= if ( fRCUon[target] ) { // Check if Fec is on if ( !fDB->getRowValueAsInt(fDBfp->QAll_Fec_ON_FEC) ) { // This altro is on a fec which is disabled sprintf(desc, "FEC disabled (ON_FEC=0, branch %d, fec %d)", branch, fec); fLogger->appendWarning(desc); // Write to config file for offline if ( fFile && (tag != 0) ) { for ( int32_t channel = 0; channel < 16; channel++ ) { *fOfsAltro << roc << "\t" << pm.GetPadRow2(branch, fec, altro, channel, rcu) << "\t" << pm.GetPad2(branch, fec, altro, channel, rcu) << "\t" << 1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << endl; } } continue; } // Fill AFL container fAFL[target]->fill(branch, fec, true); // Check if Altro is on if ( !fDB->getRowValueAsInt(fDBfp->QAll_Altro_ON_ALTRO) ) { sprintf(desc, "ALTRO disabled (ON_ALTRO=0, branch %d, fec %d, altro %d)", branch, fec, altro); fLogger->appendWarning(desc); // Write to config file for offline if ( fFile && (tag != 0) ) { for ( int32_t channel = 0; channel < 16; channel++ ) { *fOfsAltro << roc << "\t" << pm.GetPadRow2(branch, fec, altro, channel, rcu) << "\t" << pm.GetPad2(branch, fec, altro, channel, rcu) << "\t" << 1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << endl; } } continue; } // Tail Filter is enabled in this ALTRO? fConfigTCparam = (fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCF2_FLT_EN) == 1) ? true : false; zsThr = fDB->getRowValueAsInt(fDBfp->QAll_Altro_ZSTHR_ZS_THR); aqStart = fDB->getRowValueAsInt(fDBfp->QAll_Altro_TRCFG_ACQ_START); aqStop = fDB->getRowValueAsInt(fDBfp->QAll_Altro_TRCFG_ACQ_END); // Trigger on L0? If yes => read more time bins if ( trg_mode == 1 ) aqStop += trigger_offset; if ( aqStop > maxtb ) aqStop = maxtb; // // ===== Write ALTRO channel registers ===== // for ( int32_t channel = 0; channel < 16; channel++ ) { if ( fDB->getRowValueAsInt(fDBfp->QAll_Altro_ON_CHANNEL[channel]) == 0 ) { sprintf(desc, "Channel disabled (ON_CHANNEL%02d=0, branch %d, fec %d, altro %d)", channel, branch, fec, altro); fLogger->appendWarning(desc); // Write to config file for offline that this channel is masked if ( fFile && (tag != 0) ) { *fOfsAltro << roc << "\t" << pm.GetPadRow2(branch, fec, altro, channel, rcu) << "\t" << pm.GetPad2(branch, fec, altro, channel, rcu) << "\t" << 1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << "\t" << -1 << endl; } continue; } // Readout List and/or ACL fReadoutList[target]->fill(branch, fec, altro, channel); // this channel is on // Tail Filter parameters. Write only if needed for performance reasons ... if ( (tag == 1) || fConfigTCparam ) { // Six tail cancellation parameters per channel k1 = fDB->getRowValueAsInt(fDBfp->QAll_Altro_K1_CHANNEL[channel]); data = fALTRO->sendK1(branch, fec, altro, channel, k1); fDataBlock[target]->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); k2 = fDB->getRowValueAsInt(fDBfp->QAll_Altro_K2_CHANNEL[channel]); data = fALTRO->sendK2(branch, fec, altro, channel, k2); fDataBlock[target]->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); k3 = fDB->getRowValueAsInt(fDBfp->QAll_Altro_K3_CHANNEL[channel]); data = fALTRO->sendK3(branch, fec, altro, channel, k3); fDataBlock[target]->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); l1 = fDB->getRowValueAsInt(fDBfp->QAll_Altro_L1_CHANNEL[channel]); data = fALTRO->sendL1(branch, fec, altro, channel, l1); fDataBlock[target]->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); l2 = fDB->getRowValueAsInt(fDBfp->QAll_Altro_L2_CHANNEL[channel]); data = fALTRO->sendL2(branch, fec, altro, channel, l2); fDataBlock[target]->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); l3 = fDB->getRowValueAsInt(fDBfp->QAll_Altro_L3_CHANNEL[channel]); data = fALTRO->sendL3(branch, fec, altro, channel, l3); fDataBlock[target]->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); } else { k1 = k2 = k3 = l1 = l2 = l3 = 0; } // FPED value fPed = fDB->getRowValueAsInt(fDBfp->QAll_Altro_VFPED_CHANNEL[channel]); data = fALTRO->sendVFPED(branch, fec, altro, channel, fPed); fDataBlock[target]->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); // Write to config file for offline if ( fFile && (tag != 0) ) { *fOfsAltro << roc << "\t" << pm.GetPadRow2(branch, fec, altro, channel, rcu) << "\t" << pm.GetPad2(branch, fec, altro, channel, rcu) << "\t" << 0 << "\t" << fPed << "\t" << zsThr << "\t" << aqStart << "\t" << aqStop << "\t" << k1 << "\t" << k2 << "\t" << k3 << "\t" << l1 << "\t" << l2 << "\t" << l3 << endl; } } // end channel loop // // ===== Write global ALTRO registers ===== // data = fALTRO->sendZSTHR(branch, fec, altro, fALTRO->codeZSTHR(fDB->getRowValueAsInt(fDBfp->QAll_Altro_ZSTHR_OFFSET), zsThr)); fDataBlock[target]->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); data = fALTRO->sendBCTHR(branch, fec, altro, fALTRO->codeBCTHR(fDB->getRowValueAsInt(fDBfp->QAll_Altro_BCTHR_THR_HI), fDB->getRowValueAsInt(fDBfp->QAll_Altro_BCTHR_THR_LOW))); fDataBlock[target]->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); data = fALTRO->sendTRCFG(branch, fec, altro,fALTRO->codeTRCFG(aqStart, aqStop)); fDataBlock[target]->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); data = fALTRO->sendDPCFG(branch, fec, altro, fALTRO->codeDPCFG(fALTRO->codeZS_CFG(fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCFG_ZS_GF), fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCFG_ZS_PRE), fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCFG_ZS_POST), fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCFG_ZS_EN)), fALTRO->codeBC2_CFG(fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCFG_BC2_PRE), fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCFG_BC2_POST), fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCFG_BC2_EN)), fALTRO->codeBC1_CFG(fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCFG_BC1_MODE), fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCFG_BC1_POL)))); fDataBlock[target]->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); data = fALTRO->sendDPCF2(branch, fec, altro, fALTRO->codeDPCF2(fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCF2_PTRG), fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCF2_BUF), fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCF2_FLT_EN), fDB->getRowValueAsInt(fDBfp->QAll_Altro_DPCF2_PWSV))); fDataBlock[target]->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); } // end if ( fRCUon[target] ) } // end row (ALTRO) loop fDB->deleteTransaction(); if ( fFile ) { // close config output files fOfsAltro->close(); fOfsRcu->close(); delete fOfsAltro; delete fOfsRcu; } } catch(SQLException& exception) { sprintf(desc, "AllPartitionConfigData query: %s", exception.what()); fLogger->appendTime(); fLogger->appendError(desc); fError.push_back(desc); return -1; } catch(TpcException& exception) { sprintf(desc, "TPCCommandCoderDBcache::createDataBlocks(tag): %s", exception.what()); fLogger->appendTime(); fLogger->appendError(desc); fError.push_back(desc); return -1; } return 0; // No Error } //=========================================================================== int32_t TPCCommandCoderDBcache::createDataBlock(char* target,int tag){ // // Create the data block. Return length (in bytes!). // // If negative value is returned, an error occured. All errors are added to a // vector. The InterComLayer will analyse the errors in case of an negative // return value. // if ( fFirstCall && (fError.size() != 0) ) { for ( uint32_t i = 0; i < fError.size(); i++ )fLogger->appendError(fError.at(i)); fError.push_back("Error at start of createDataBlock"); return -1; // Error } char desc[256]; string tempstring; // Get side, sector and partition from target name (e.g. TPC-FEE_1_12_1) string strtarget = target; uint32_t pos1_ = strtarget.find( "_", 0 ); uint32_t pos2_ = strtarget.find( "_", (pos1_+1) ); uint32_t pos3_ = strtarget.find( "_", (pos2_+2) ); int32_t side = strtonum(strtarget.substr((pos1_+1), (pos2_-pos1_-1 ))); int32_t sector = strtonum(strtarget.substr((pos2_+1), (pos3_-pos2_-1 ))); int32_t rcu = strtonum(strtarget.substr((pos3_+1), (strtarget.size()-pos3_-1))); fSide = side; // Save the target number (0...215) for the getdatablock function fTarget = side*6*18+sector*6+rcu; if ( tag == 0 ) { // ======================================================= // ======================== TAG 0 ======================== // ======================================================= fLogger->append(""); sprintf(desc, "===== %s =====", target); fLogger->append(desc); fLogger->appendTime(); tempstring="*Sending reset and reconfigure"; fLogger->append(tempstring.c_str()); // reset fDataBlock[fTarget]->reset(); // Execute the locally stored configuration fDataBlock[fTarget]->setDoFastSOR2(); // Second configuration step through DDL? fDataBlock[fTarget]->setExternalConfiguration(false); // DCS only // Set RCU ID in configuration block fDataBlock[fTarget]->setHardwareAddress(fTarget); // Reset fDataBlock[fTarget]->fillRcu((uint32_t)fRCUce->sendGLB_RESET()); // Send command to syncronise (armSYNC) fDataBlock[fTarget]->fillRcu((uint32_t)fRCUce->sendRCU_SYNC_SCLK_L1TTC()); } else { // ======================================================= // ===================== DB Values ======================= // ======================================================= time_t rawtime; time(&rawtime); if ( abs(rawtime-fLastCallTime) > 300 ) { int32_t ret = createDataBlocks(tag); if ( ret<0 ) return -1; fLastCallTime = rawtime; } // Add at beginning of data block AFL and resets fDataBlock[fTarget]->fillAtStartRcu((uint32_t)fRCUce->sendGLB_RESET()); if (fRCUon[fTarget]) fDataBlock[fTarget]->fillAtStartRcu(fAFL[fTarget]->get()); // AFL else fDataBlock[fTarget]->fillAtStartRcu((uint32_t)0); // keep FECs off fDataBlock[fTarget]->fillAtStartRcu((uint32_t)fRCUce->sendRCU_WRITE_AFL(), false); fDataBlock[fTarget]->fillAtStartRcu((uint32_t)fRCUce->sendGLB_RESET()); // Add Readout List Memory try { fReadoutList[fTarget]->makeReadoutListFromAclV21(rcu); // padrow after padrow, alternating branches fReadoutList[fTarget]->finalize(); fDataBlock[fTarget]->fillRcu((uint32_t)fRCUce->sendRCU_WRITE_ACL(fReadoutList[fTarget]->size()), false); for ( uint32_t i = 0; i < fReadoutList[fTarget]->size(); i++ ) fDataBlock[fTarget]->fillRcu(fReadoutList[fTarget]->at(i), false); // payload, no tailer fDataBlock[fTarget]->fillRcu((uint32_t)fRCUce->sendCE_CMD_TAILER(), false); // tailer } catch(TpcException& ea) { sprintf(desc, "%s", ea.what()); fLogger->appendTime(); fLogger->appendError(desc); fError.push_back(desc); } fLogger->append(""); sprintf(desc, "===== %s =====", target); fLogger->append(desc); fLogger->appendTime(); tempstring="*Sending configure command block"; fLogger->append(tempstring.c_str()); } // end if (tag==0) // Finalize data block (add headers and tailers, calculate size) try { fDataBlock[fTarget]->finalize(); sprintf(desc, "*Size: %d bytes", (int)(fDataBlock[fTarget]->size()*4)); fLogger->append(desc); } catch(TpcException& exception) { sprintf(desc, "%s", exception.what()); fLogger->appendTime(); fLogger->appendError(desc); fError.push_back(desc); return -1; // Error } if (fFirstCall) fFirstCall = false; // CoCo was called // Return the length of the data block (in bytes!) return (int)(fDataBlock[fTarget]->size()*4); } //=========================================================================== vector& TPCCommandCoderDBcache::getError(){ // // Get Errors // return fError; } //=========================================================================== std::string& TPCCommandCoderDBcache::getCoCoInfo(){ // // Get Information about Command Coder // return fVersion; } //=========================================================================== int32_t TPCCommandCoderDBcache::strtonum(string number) { // // convert string to number // char * strolConversionCheck; if ( number[0] == '0' ) number.erase(0, 1); int32_t retval = strtol(number.c_str(), &strolConversionCheck, 0); return retval; } //=========================================================================== CommandCoderBase* getCoCoInst(void){ // // Get Command Coder Instance. This is called by e.g. InterComLayer in order to // use the Command Coder from the shared object library. // static TPCCommandCoderDBcache instance; return &instance; }