#include "TPCCommandCoderDB.h" #define CoCoVersion "TPCCommandCoderDB" //=========================================================================== TPCCommandCoderDB::TPCCommandCoderDB() { // // Constructor: Setup and connect to DB // // Switch to write binary IMEM and RCU CFG data to files fBinaryFiles = true; // Switch to enable Board Controller configuration fConfigBCs = true; #ifdef P2 fdbSystem = 0; // 0 = Oracle@P2 fOutputFilePath = "/home/tpc/configs/"; fDebugFileName = fOutputFilePath+"TPCCommandCoderDB.log"; fCoCoBinaryFilePath = "/home/tpc/dcbro/imem/"; // here the CoCo puts the files #else fdbSystem = 2; // 1 = Oracle@DCSlab; 2 = Oracle test (devdb10). fDebugFileName = "/tmp/TPCCommandCoderDB.log"; fOutputFilePath = "/tmp/"; fCoCoBinaryFilePath = "/home/fee/dcbro/imem/"; // here the CoCo puts the files #endif string tempstring; char desc[256]; fReadoutList = new ReadoutList(); fDataBlock = new RcuContainer(); fALTRO = new AltroCommandCoder(); fBC = new BoardControllerCommandCoder(); fRCU = new RCUCommandCoder(); fRCUce = new RCUControlEngine(); fDBfp = new FERODBFieldPositions(); fAFL = new Afl(); fDB = new OracleDB(); fFirstCall = true; // CoCo was called first time fConfigTCparam = true; // false -> Fast configuration writes only non-zero values fError.clear(); fLogger = Logger::getInstance(); fLogger->setlogfilename(fDebugFileName.c_str()); fLogger->setDebugLevel(1); fDBqc = NULL; fACL = NULL; fwatchDogTimeout = 120; fLogger->append( "======================================="); fLogger->appendTime(); fLogger->append("TPCCommandCoderDB 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& ea) { sprintf(desc, "%s (%s)", ea.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& ea) { sprintf(desc, "%s (%s)", ea.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-dcs-tpc"; pdbConnectString = "devdb10"; try { fDB->connect(pdbUser, pdbPassword, pdbConnectString); } catch(SQLException& ea) { sprintf(desc, "%s (%s)", ea.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 desc[255] = 0; if ( isConnected()) { tempstring= "Successfully connected to DB "+ pdbConnectString; fLogger->append(tempstring.c_str()); fLogger->append( "======================================="); } } //=========================================================================== TPCCommandCoderDB::~TPCCommandCoderDB() { // // Destructor. Close DB connection. // char desc[256]; try { fDB->disconnect(); } catch(SQLException& ea) { fLogger->appendTime(); fLogger->append(ea.what()); strncpy(desc, ea.what(), 255); fError.push_back(desc); } if ( fBinaryFiles ) { delete fOfsIMEM; delete fOfsRcuCfg; } delete fOfsAltro; delete fOfsRcu; delete fDB; delete fDBqc; delete fDBfp; delete fRCU; delete fALTRO; delete fBC; delete fRCUce; delete fDataBlock; delete fAFL; delete fReadoutList; if (fACL) delete fACL; } //=========================================================================== void TPCCommandCoderDB::reset() { // // Reset // try { fDataBlock->reset(); if (fACL) fACL->reset(); fReadoutList->reset(); fAFL->reset(); } catch(TpcException& ea) { fLogger->appendTime(); fLogger->append(ea.what()); char desc[256]; strncpy(desc, ea.what(), 255); fError.push_back(desc); } } //=========================================================================== uint32_t* TPCCommandCoderDB::getDataBlock() { // // Send the data block // return fDataBlock->getDataBlock(); } //=========================================================================== int32_t TPCCommandCoderDB::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 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 } if ( fFirstCall && (fError.size() != 0) ) { fLogger->appendTime(); 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 } reset(); Mapping pm; // The mapping of hardware adresses to pads // 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))); int32_t roc = pm.GetRocFromPatch(side, sector, rcu); sprintf(target, "TPC-FEE_%d_%02d_%d", side, sector, rcu); 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; bool rcuON = false; const uint32_t maxtb = 1008; 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 en_int_ba = 0; int32_t zs_cfg = -1; int32_t bc2_cfg = -1; int32_t bc1_cfg = -1; int32_t pwsv = -1; int32_t flt_en = -1; int32_t nbuf = -1; int32_t ptrg = -1; int32_t bc1mode = -1; int32_t bc2en = -1; int32_t zsen = -1; 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; int32_t trigger_offset = 0; // related to start-of-acquisition at L0/L1 if ( tag < 0 ) { trg_mode = 1; tag = abs(tag); } if ( tag > 0 ) { fOutputFileNameRcu = fOutputFilePath+"RCUconfig_"+target+".data"; fOfsRcu = new ofstream(); // Configuration data file for offline fOfsRcu->open(fOutputFileNameRcu.c_str(), ios::out); *fOfsRcu << 98 << endl; fOutputFileNameAltro = fOutputFilePath+"ALTROconfig_"+target+".data"; fOfsAltro = new ofstream(); // Configuration data file for offline fOfsAltro->open(fOutputFileNameAltro.c_str(), ios::out); *fOfsAltro << 99 << endl; if ( fBinaryFiles ) { fImemFileName = fCoCoBinaryFilePath+target+"_FEESERVER_IMEM"; fRcuCfgFileName = fCoCoBinaryFilePath+target+"_FEESERVER_REG_CFG"; fOfsIMEM = new ofstream(); fOfsRcuCfg = new ofstream(); fOfsIMEM->open(fImemFileName.c_str(), ios::out|ios::binary); fOfsRcuCfg->open(fRcuCfgFileName.c_str(), ios::out|ios::binary); } } else { fOfsRcu = NULL; fOfsAltro = NULL; fOfsIMEM = NULL; fOfsRcuCfg = NULL; } fLogger->append(""); sprintf(desc, "===== %s =====", target); fLogger->append(desc); fLogger->appendTime(); if ( tag == 0 ) tempstring="*Sending reset&reconfigure"; else tempstring="*Assembling configure command block from DB"; fLogger->append(tempstring.c_str()); // ====================================================================== // 1) Contact DB to get the RCU ID and configuration // ====================================================================== if ( tag > 0 ) { try { // Execute RCU query (mainly to get RCU id) fDB->createTransaction(); fDB->setSQLgetRowCount(fDBqc->getSqlBindSelectPartitionData()); fDB->setNumber(0, tag); fDB->setNumber(1, side); fDB->setNumber(2, sector); fDB->setNumber(3, rcu); fDB->executeQuery(); fDB->getRow(); int32_t rowcount = fDB->getRowValueAsInt(0); if ( rowcount != 1 ) { sprintf(desc, "*Error: Got strange number of rows from DB (rcu query): %d", rowcount); fLogger->appendTime(); fLogger->appendError(desc); fError.push_back(desc); return -1; // Error } fDB->deleteTransaction(); // Get the row with rcu data fDB->createTransaction(); fDB->setSQL(fDBqc->getSqlBindSelectPartitionData()); fDB->setNumber(0, tag); fDB->setNumber(1, side); fDB->setNumber(2, sector); fDB->setNumber(3, rcu); fDB->executeQuery(); fDB->getRow(); rcuID = fDB->getRowValueAsInt(fDBfp->RCUid); rcuON = (bool)fDB->getRowValueAsInt(fDBfp->RCUon); // Some registers for RCU Fw V2 nsam_ev = (uint32_t)fDB->getRowValueAsInt(fDBfp->RCUaltroif_nsam_ev); clk_ratio = (uint32_t)fDB->getRowValueAsInt(fDBfp->RCUaltroif_clk_ratio); cstb_delay = (uint32_t)fDB->getRowValueAsInt(fDBfp->RCUaltroif_cstb_delay); chan_skip = (uint32_t)fDB->getRowValueAsInt(fDBfp->RCUrdomod_skip_empty); sparse_rdo = (uint32_t)fDB->getRowValueAsInt(fDBfp->RCUrdomod_sparse_rdo); meb_mode = (uint32_t)fDB->getRowValueAsInt(fDBfp->RCUrdomod_meb_mode); dis_rdyrx = (uint32_t)fDB->getRowValueAsInt(fDBfp->RCUrdomod_disable_rdyrx); cdh_version = (uint32_t)fDB->getRowValueAsInt(fDBfp->RCUttc_control_cdh_version); l1_latency = (uint32_t)fDB->getRowValueAsInt(fDBfp->RCUttc_l1_latency); l1_window = (uint32_t)fDB->getRowValueAsInt(fDBfp->RCUttc_l1_latency_window); l1_msg_lat_min = (uint32_t)fDB->getRowValueAsInt(fDBfp->RCUttc_l1_msg_latency_min); l1_msg_lat_max = (uint32_t)fDB->getRowValueAsInt(fDBfp->RCUttc_l1_msg_latency_max); l2_lat_min = (uint32_t)fDB->getRowValueAsInt(fDBfp->RCUttc_l2_latency_min); l2_lat_max = (uint32_t)fDB->getRowValueAsInt(fDBfp->RCUttc_l2_latency_max); roi_lat_min = (uint32_t)fDB->getRowValueAsInt(fDBfp->RCUttc_roi_latency_min); roi_lat_max = (uint32_t)fDB->getRowValueAsInt(fDBfp->RCUttc_roi_latency_max); roi_conf1 = (uint32_t)fDB->getRowValueAsInt(fDBfp->RCUttc_roi_config1); roi_conf2 = (uint32_t)fDB->getRowValueAsInt(fDBfp->RCUttc_roi_config2); en_int_ba = (uint32_t)fDB->getRowValueAsInt(fDBfp->RCUen_int_ba); //fDB->freeResult(); fDB->deleteTransaction(); // 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 ( !rcuON ){ sprintf(desc, "*RCU off (rcuON=%d).", rcuON); fLogger->append(desc); if ( tag != 0 ) { *fOfsRcu << pm.GetDDLfromPatch(side, sector, rcu) << " " << rcuON << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << " " << -1 << endl; } } else { sprintf(desc, "*RCU CFG: RCU_ID=%d: tag=%d | rcuON=%d | chan_skip=%d | sparse_rdo=%d | clk_ratio=%d", rcuID, tag, rcuON, chan_skip, sparse_rdo, clk_ratio); fLogger->append(desc); sprintf(desc, "*TRG_MODE: L%d | EN_INT_BA=0x%x", abs((int)(trg_mode-1)), en_int_ba); fLogger->append(desc); if ( tag != 0 ) { *fOfsRcu << pm.GetDDLfromPatch(side, sector, rcu) << " " << rcuON << " " << 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; } } } catch(SQLException& ea) { sprintf(desc, "%s: %s", target, ea.what()); fLogger->appendTime(); fLogger->appendError(desc); fError.push_back(desc); return -1; } catch(TpcException& ea) { sprintf(desc, "%s: %s", target, ea.what()); fLogger->appendTime(); fLogger->appendError(desc); fError.push_back(desc); return -1; } } // end if ( tag > 0 ) // ====================================================================== // 2) Start filling Data Buffer // ====================================================================== // DCS only fDataBlock->setExternalConfiguration(false); // Set RCU ID in configuration block fDataBlock->setHardwareAddress(rcuID); // Set filenames for binary files on DCS boards fDcsBinaryFilePath = "/mnt/dcbro/imem/"; // here the feeserver will find the files fDataBlock->setDcsImemFileName(fDcsBinaryFilePath+target+"_FEESERVER_IMEM"); fDataBlock->setDcsRcuCfgFileName(fDcsBinaryFilePath+target+"_FEESERVER_REG_CFG"); if ( tag == 0 ) { // The first thing is resetting the RCU fDataBlock->fillRcu((uint32_t)fRCUce->sendRCU_RESET()); // Disable Interrupt handling before ALTRO and BC config fDataBlock->fillRcu((uint32_t)fRCUce->sendRCU_WRITE_EN_INT_BA(), false); fDataBlock->fillRcu((uint32_t)0); // Revert ACTFECLIST fDataBlock->fillRcu((uint32_t)fRCUce->sendRCU_REG_CFG_EXECUTE_SINGLE(), false); fDataBlock->fillRcu((uint32_t)AFL_REG_ADD); // The second thing is reconfigure the BCs fDataBlock->fillRcu((uint32_t)fRCUce->sendRCU_CONFGFEC()); // Again resetting fDataBlock->fillRcu((uint32_t)fRCUce->sendGLB_RESET()); // Send command to synchronise all clocks (armSYNC) fDataBlock->fillRcu((uint32_t)fRCUce->sendRCU_SYNC_SCLK_L1TTC()); // Execute the configuration not from DB but from file fDataBlock->setDoFastSOR2(); // Enable interrupt handling after ALTRO and BC config if it was enabled before fDataBlock->appendRcu((uint32_t)fRCUce->sendRCU_REG_CFG_EXECUTE_SINGLE(), false); fDataBlock->appendRcu(((uint32_t)EN_INT_BA_REG_ADD)); } else { // ====================================================================== // 3) Contact DB to get channel-by-channel values (Altro configuration data) // ====================================================================== vector fImem; // copy of the data try { // Store data on DCS board; execute locally saved instructions fDataBlock->setConfigurePhysics2(); // Execute query (get size of all config data) fDB->createTransaction(); fDB->setSQLgetRowCount(fDBqc->getSqlBindSelectPartitionConfigData()); fDB->setNumber(0, rcuID); fDB->executeQuery(); fDB->getRow(); int32_t rowcount = fDB->getRowValueAsInt(0); sprintf(desc, "*PartitionConfigData query returned %d rows.", rowcount); fLogger->append(desc); fDB->deleteTransaction(); 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 } // =========================================================== // ================= Loop through all Altros ================= // =========================================================== // Execute query (get all config data) fDB->createTransaction(); fDB->setSQL(fDBqc->getSqlBindSelectPartitionConfigData()); fDB->setNumber(0, rcuID); fDB->executeQuery(); int32_t currentfec = -1; for ( int32_t rowCounter = 0; rowCounter < rowcount; rowCounter++ ) { fDB->getRow(); branch = fDB->getRowValueAsInt(fDBfp->FECbranchPosition); fec = fDB->getRowValueAsInt(fDBfp->FECposition); altro = fDB->getRowValueAsInt(fDBfp->ALTROposition); //debug output sprintf(desc, "Next row! Branch=%d, fec=%d, altro=%d (hw adress=%d)", branch, fec, altro, fALTRO->codeAddress(branch, fec, altro, 0)); fLogger->appendInfo(desc); //debug output for(int32_t fieldCounter = 0; fieldCounter < fDB->getFieldCount(); fieldCounter++) { tempstring = fDB->getRowValueAsString(fieldCounter); sprintf(desc,"Branch=%d, fec=%d, altro=%d: Result from column %d -> %s", branch, fec, altro, fieldCounter, tempstring.c_str()); fLogger->appendDebug(desc); } // Check if Fec is active if ( !fDB->getRowValueAsInt(fDBfp->FEConFEC) ) { // This altro is on a fec which is off sprintf(desc, "FEC disabled (ON_FEC=0, branch %d, fec %d)", branch, fec); fLogger->appendWarning(desc); } else if ( !fDB->getRowValueAsInt(fDBfp->FECrdoFEC) ) { // This altro is on a fec which is not to be read out sprintf(desc, "FEC not to be read out (RDO_FEC=0, branch %d, fec %d)", branch, fec); fLogger->appendWarning(desc); } // Write to config file for offline if ( !fDB->getRowValueAsInt(fDBfp->FEConFEC) || !fDB->getRowValueAsInt(fDBfp->FECrdoFEC) ) { if ( 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; } } } // Do not continue configuring if this FEC is off if ( !fDB->getRowValueAsInt(fDBfp->FEConFEC) ) continue; // Fill AFL fAFL->fill(branch, fec, true); if ( rcuON ) { if ( currentfec != (((branch&1)<<4)|(fec&0xf)) ) { // This is a new FEC currentfec = (((branch&1)<<4)|(fec&0xf)); sprintf(desc, "New FEC! Get board controller registers. Branch=%d, fec=%d!", branch, fec); fLogger->appendDebug(desc); // Fill FEC Board Controler registers if (fConfigBCs) { // Set threshold values data = fBC->sendT_TH(branch, fec, fDB->getRowValueAsInt(fDBfp->FECbcTth)); fDataBlock->fillBc(branch, fec, fRCU->sendBoardControllerInstruction(data), false); fImem.push_back(fRCU->sendBoardControllerInstruction(data)); data = fBC->sendAV_TH(branch, fec, fDB->getRowValueAsInt(fDBfp->FECbcAVth)); fDataBlock->fillBc(branch, fec, fRCU->sendBoardControllerInstruction(data), false); fImem.push_back(fRCU->sendBoardControllerInstruction(data)); data = fBC->sendAC_TH(branch, fec, fDB->getRowValueAsInt(fDBfp->FECbcACth)); fDataBlock->fillBc(branch, fec, fRCU->sendBoardControllerInstruction(data), false); fImem.push_back(fRCU->sendBoardControllerInstruction(data)); data = fBC->sendDV_TH(branch, fec, fDB->getRowValueAsInt(fDBfp->FECbcDVth)); fDataBlock->fillBc(branch, fec, fRCU->sendBoardControllerInstruction(data), false); fImem.push_back(fRCU->sendBoardControllerInstruction(data)); data = fBC->sendDC_TH(branch, fec, fDB->getRowValueAsInt(fDBfp->FECbcDCth)); fDataBlock->fillBc(branch, fec, fRCU->sendBoardControllerInstruction(data), false); fImem.push_back(fRCU->sendBoardControllerInstruction(data)); // Set CSR0: Interrupt mask data = fBC->sendCSR0(branch, fec, fDB->getRowValueAsInt(fDBfp->FECbcCSR0)); fDataBlock->fillBc(branch, fec, fRCU->sendBoardControllerInstruction(data), false); fImem.push_back(fRCU->sendBoardControllerInstruction(data)); // Set CSR2: Switch voltage regulators etc data = fBC->sendCSR2(branch, fec, fDB->getRowValueAsInt(fDBfp->FECbcCSR2)); fDataBlock->fillBc(branch, fec, fRCU->sendBoardControllerInstruction(data), false); fImem.push_back(fRCU->sendBoardControllerInstruction(data)); // Clear CSR1 fDataBlock->fillBc(branch, fec, (uint32_t)fRCU->sendBoardControllerCommand(fBC->sendCSR1CLR(branch, fec)), false); //fImem.push_back((uint32_t)fRCU->sendBoardControllerCommand(fBC->sendCSR1CLR(branch, fec))); /* 32bit does not work */ } } // end if new fec // Check if Altro is on if ( !fDB->getRowValueAsInt(fDBfp->ALTROon) ) { // ALTRO is off 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 ( 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->ALTROdbcf2FLTen) == 1) ? true : false; zsThr = fDB->getRowValueAsInt(fDBfp->ALTROzsthrZSthr); aqStart = fDB->getRowValueAsInt(fDBfp->ALTROtrcvfgACQstart); aqStop = fDB->getRowValueAsInt(fDBfp->ALTROtrcvfgACQend); // 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->ALTROonChannel[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 ( 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; } // Fill Readout List Memory (ACL) if ( fDB->getRowValueAsInt(fDBfp->FECrdoFEC) ) fReadoutList->fill(branch, fec, altro, channel); // This channel is to be read out // Tail Filter parameters. Write only if needed for performance reasons ... if ( (tag == 1) || fConfigTCparam ) { // Six tail cancellation parameters per channel k1 = fDB->getRowValueAsInt(fDBfp->ALTROk1Channel[channel]); data = fALTRO->sendK1(branch, fec, altro, channel, k1); fDataBlock->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); fImem.push_back(fRCU->sendAltroInstruction(data)); k2 = fDB->getRowValueAsInt(fDBfp->ALTROk2Channel[channel]); data = fALTRO->sendK2(branch, fec, altro, channel, k2); fDataBlock->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); fImem.push_back(fRCU->sendAltroInstruction(data)); k3 = fDB->getRowValueAsInt(fDBfp->ALTROk3Channel[channel]); data = fALTRO->sendK3(branch, fec, altro, channel, k3); fDataBlock->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); fImem.push_back(fRCU->sendAltroInstruction(data)); l1 = fDB->getRowValueAsInt(fDBfp->ALTROl1Channel[channel]); data = fALTRO->sendL1(branch, fec, altro, channel, l1); fDataBlock->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); fImem.push_back(fRCU->sendAltroInstruction(data)); l2 = fDB->getRowValueAsInt(fDBfp->ALTROl2Channel[channel]); data = fALTRO->sendL2(branch, fec, altro, channel, l2); fDataBlock->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); fImem.push_back(fRCU->sendAltroInstruction(data)); l3 = fDB->getRowValueAsInt(fDBfp->ALTROl3Channel[channel]); data = fALTRO->sendL3(branch, fec, altro, channel, l3); fDataBlock->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); fImem.push_back(fRCU->sendAltroInstruction(data)); } else { k1 = k2 = k3 = l1 = l2 = l3 = 0; } // FPED value fPed = fDB->getRowValueAsInt(fDBfp->ALTROvfpedChannel[channel]); data = fALTRO->sendVFPED(branch, fec, altro, channel, fPed); fDataBlock->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); fImem.push_back(fRCU->sendAltroInstruction(data)); // Write to config file for offline if ( 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->ALTROzsthrOffset), zsThr)); fDataBlock->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); fImem.push_back(fRCU->sendAltroInstruction(data)); data = fALTRO->sendBCTHR(branch, fec, altro, fALTRO->codeBCTHR(fDB->getRowValueAsInt(fDBfp->ALTRObcthrTHRhi), fDB->getRowValueAsInt(fDBfp->ALTRObcthrTHRlow))); fDataBlock->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); fImem.push_back(fRCU->sendAltroInstruction(data)); data = fALTRO->sendTRCFG(branch, fec, altro,fALTRO->codeTRCFG(aqStart, aqStop)); fDataBlock->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); fImem.push_back(fRCU->sendAltroInstruction(data)); data = fALTRO->sendDPCFG(branch, fec, altro, fALTRO->codeDPCFG(fALTRO->codeZS_CFG(fDB->getRowValueAsInt(fDBfp->ALTROdpcfgZSgf), fDB->getRowValueAsInt(fDBfp->ALTROdpcfgZSpre), fDB->getRowValueAsInt(fDBfp->ALTROdpcfgZSpost), fDB->getRowValueAsInt(fDBfp->ALTROdpcfgZSen)), fALTRO->codeBC2_CFG(fDB->getRowValueAsInt(fDBfp->ALTROdpcfgBC2pre), fDB->getRowValueAsInt(fDBfp->ALTROdpcfgBC2post), fDB->getRowValueAsInt(fDBfp->ALTROdpcfgBC2en)), fALTRO->codeBC1_CFG(fDB->getRowValueAsInt(fDBfp->ALTROdpcfgBC1mode), fDB->getRowValueAsInt(fDBfp->ALTROdpcfgBC1pol)))); fDataBlock->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); fImem.push_back(fRCU->sendAltroInstruction(data)); data = fALTRO->sendDPCF2(branch, fec, altro, fALTRO->codeDPCF2(fDB->getRowValueAsInt(fDBfp->ALTROdbcf2PTRG), fDB->getRowValueAsInt(fDBfp->ALTROdbcf2BUF), fDB->getRowValueAsInt(fDBfp->ALTROdbcf2FLTen), fDB->getRowValueAsInt(fDBfp->ALTROdbcf2PWSV))); fDataBlock->fillAltro(branch, fec, altro, fRCU->sendAltroInstruction(data)); fImem.push_back(fRCU->sendAltroInstruction(data)); // 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!!! if (bc1mode<0) bc1mode = fDB->getRowValueAsInt(fDBfp->ALTROdpcfgBC1mode); if (zsen <0) zsen = fDB->getRowValueAsInt(fDBfp->ALTROdpcfgZSen); if (bc2en <0) bc2en = fDB->getRowValueAsInt(fDBfp->ALTROdpcfgBC2en); if (zs_cfg <0) zs_cfg = fALTRO->codeZS_CFG(fDB->getRowValueAsInt(fDBfp->ALTROdpcfgZSgf), fDB->getRowValueAsInt(fDBfp->ALTROdpcfgZSpre), fDB->getRowValueAsInt(fDBfp->ALTROdpcfgZSpost), zsen); if (bc2_cfg<0) bc2_cfg = fALTRO->codeBC2_CFG(fDB->getRowValueAsInt(fDBfp->ALTROdpcfgBC2pre), fDB->getRowValueAsInt(fDBfp->ALTROdpcfgBC2post), bc2en); if (bc1_cfg<0) bc1_cfg = fALTRO->codeBC1_CFG(bc1mode, fDB->getRowValueAsInt(fDBfp->ALTROdpcfgBC1pol)); if (pwsv <0) pwsv = fDB->getRowValueAsInt(fDBfp->ALTROdbcf2PWSV); if (flt_en <0) flt_en = fDB->getRowValueAsInt(fDBfp->ALTROdbcf2FLTen); if (nbuf <0) nbuf = fDB->getRowValueAsInt(fDBfp->ALTROdbcf2BUF); if (ptrg <0) ptrg = fDB->getRowValueAsInt(fDBfp->ALTROdbcf2PTRG); } // end if ( rcuON ) } // end row loop if ( rcuON ) { sprintf(desc, "*ALTRO CFG: BC1_MODE=0x%x | FLT_EN=%d | BC2_EN=%d | PWSV=%d | ZS_EN=%d | PTRG=0x%x", bc1mode, flt_en, bc2en, pwsv, zsen, ptrg); fLogger->append(desc); } //fDB->freeResult(); fDB->deleteTransaction(); } catch (SQLException& ea) { sprintf(desc, "%s", ea.what()); fLogger->appendTime(); fLogger->appendError(desc); fError.push_back(desc); } catch(TpcException& ea) { sprintf(desc, "%s", ea.what()); fLogger->appendTime(); fLogger->appendError(desc); fError.push_back(desc); } // dump binary IMEM file if ( rcuON && fBinaryFiles ) { uint32_t imemsize = fImem.size()*2; uint32_t *imem = new uint32_t[imemsize]; for ( uint32_t index=0; index<(imemsize/2); index++ ) { imem[index*2 ] = fImem[index]>>32; imem[index*2+1] = fImem[index]&0xFFFFFFFF; } fOfsIMEM->write((char*)imem, imemsize*4); if ( imem ) { delete[] imem; imem=0; } if ( fOfsIMEM ) fOfsIMEM->close(); } if ( !rcuON && (tag != 0) ) { // RCU is off for (branch = 0; branch < 2; branch++ ) { int32_t maxfecs = 10; if ( (rcu==0) || (rcu==2) ) maxfecs = 9; else if ( rcu==1 ) { if ( branch==0 ) maxfecs = 13; else if ( branch==1 ) maxfecs = 12; } for ( fec = 0; fec < maxfecs; fec++ ) { for ( altro = 0; altro < 8; altro++ ) { 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; } } } } } // // ================= Fill Rcu registers ================== // // The first thing is a global reset fDataBlock->fillRcu((uint32_t)fRCUce->sendGLB_RESET()); // Disable Interrupt handling before ALTRO and BC config fDataBlock->fillRcu((uint32_t)fRCUce->sendRCU_WRITE_EN_INT_BA(), false); fDataBlock->fillRcu((uint32_t)0); // Fill AFL in data buffer ... if (rcuON) fDataBlock->fillRcuBufferAFL(fAFL->get()); else fDataBlock->fillRcuBufferAFL(0); // ... and execute it at this stage fDataBlock->fillRcu((uint32_t)fRCUce->sendRCU_REG_CFG_EXECUTE_SINGLE(), false); fDataBlock->fillRcu((uint32_t)AFL_REG_ADD); // Send reset after switching the AFL fDataBlock->fillRcu((uint32_t)fRCUce->sendGLB_RESET()); if ( rcuON ) { // Fill RCU registers for RCU Fw V2 // ALTROIF Register fDataBlock->fillRcuBufferALTROIF((uint32_t)fRCU->codeALTROIF(cstb_delay, clk_ratio, nsam_ev)); fDataBlock->fillRcu((uint32_t)fRCUce->sendRCU_REG_CFG_EXECUTE_SINGLE(), false); fDataBlock->fillRcu((uint32_t)ALTROIF_REG_ADD); // TRGCONF Register fDataBlock->fillRcuBufferTRGCONF((uint32_t)fRCU->codeTRGCONF(trg_mode)); fDataBlock->fillRcu((uint32_t)fRCUce->sendRCU_REG_CFG_EXECUTE_SINGLE(), false); fDataBlock->fillRcu((uint32_t)TRGCONF_REG_ADD); // RDOMOD Register fDataBlock->fillRcuBufferRDOMOD((uint32_t)fRCU->codeRDOMOD(chan_skip, sparse_rdo, meb_mode)); fDataBlock->fillRcu((uint32_t)fRCUce->sendRCU_REG_CFG_EXECUTE_SINGLE(), false); fDataBlock->fillRcu((uint32_t)RDOMOD_REG_ADD); // ALTROCFG1 Register fDataBlock->fillRcuBufferALTROCFG1((uint32_t)fRCU->codeALTROCFG1(zs_cfg, bc2_cfg, bc1_cfg)); fDataBlock->fillRcu((uint32_t)fRCUce->sendRCU_REG_CFG_EXECUTE_SINGLE(), false); fDataBlock->fillRcu((uint32_t)ALTROCFG1_REG_ADD); // ALTROCFG2 Register fDataBlock->fillRcuBufferALTROCFG2((uint32_t)fRCU->codeALTROCFG2(pwsv, flt_en, nbuf, ptrg)); fDataBlock->fillRcu((uint32_t)fRCUce->sendRCU_REG_CFG_EXECUTE_SINGLE(), false); fDataBlock->fillRcu((uint32_t)ALTROCFG2_REG_ADD); // RCU_ID Register fDataBlock->fillRcuBufferRCUID((uint32_t)fRCU->codeRCUID(side, sector, rcu)); fDataBlock->fillRcu((uint32_t)fRCUce->sendRCU_REG_CFG_EXECUTE_SINGLE(), false); fDataBlock->fillRcu((uint32_t)RCUID_REG_ADD); // TTC_L1_LATENCY Register fDataBlock->fillRcuBufferTTC_L1_LATENCY((uint32_t)fRCU->codeTTC_L1_LATENCY(l1_latency, l1_window)); fDataBlock->fillRcu((uint32_t)fRCUce->sendRCU_REG_CFG_EXECUTE_SINGLE(), false); fDataBlock->fillRcu((uint32_t)TTC_L1_LATENCY_REG_ADD); // TTC_L1_MSG_LATENCY Register fDataBlock->fillRcuBufferTTC_L1_MSG_LATENCY((uint32_t)fRCU->codeTTC_L1_MSG_LATENCY(l1_msg_lat_min, l1_msg_lat_max)); fDataBlock->fillRcu((uint32_t)fRCUce->sendRCU_REG_CFG_EXECUTE_SINGLE(), false); fDataBlock->fillRcu((uint32_t)TTC_L1_MSG_LATENCY_REG_ADD); // TTC_L2_LATENCY Register fDataBlock->fillRcuBufferTTC_L2_LATENCY((uint32_t)fRCU->codeTTC_L2_LATENCY(l2_lat_min, l2_lat_max)); fDataBlock->fillRcu((uint32_t)fRCUce->sendRCU_REG_CFG_EXECUTE_SINGLE(), false); fDataBlock->fillRcu((uint32_t)TTC_L2_LATENCY_REG_ADD); // Prepare the readout list try { fReadoutList->makeReadoutListFromAclV21(rcu); // padrow after padrow, alternating branches fReadoutList->finalize(); fDataBlock->fillRcu((uint32_t)fRCUce->sendRCU_WRITE_ACL(fReadoutList->size()), false); for ( uint32_t i = 0; i < fReadoutList->size(); i++ ) fDataBlock->fillRcu(fReadoutList->at(i), false); // payload, no tailer fDataBlock->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); } // Enable Interrupt handling after ALTRO and BC config. First fill EN_INT_BA register content in data buffer ... fDataBlock->fillRcuBufferEN_INT_BA(en_int_ba); // ... and execute it at this stage fDataBlock->appendRcu((uint32_t)fRCUce->sendRCU_REG_CFG_EXECUTE_SINGLE(), false); fDataBlock->appendRcu(((uint32_t)EN_INT_BA_REG_ADD)); // dump binary RCU CFG file if ( fBinaryFiles ) { vector fRcuCfg = fDataBlock->getRcuBuffer(); uint32_t cfgsize = fRcuCfg.size(); uint32_t *rcucfg = &fRcuCfg[0]; fOfsRcuCfg->write((char*)rcucfg, cfgsize*4); if ( fOfsRcuCfg ) fOfsRcuCfg->close(); } } // end if ( rcuON ) } // end if (tag==0) // // Finalize data block (add headers and tailers, calculate size) // try { fDataBlock->finalize(); } catch(TpcException& ea) { sprintf(desc, "%s", ea.what()); fLogger->appendTime(); fLogger->appendError(desc); fError.push_back(desc); return -1; // Error } if (fFirstCall) fFirstCall = false; // CoCo was called if ( tag != 0 ) { // close config output files if ( fOfsAltro ) fOfsAltro->close(); if ( fOfsRcu ) fOfsRcu->close(); } // Return the length of the data block (in 32bit words!) return (int32_t)fDataBlock->size(); } //=========================================================================== vector &TPCCommandCoderDB::getError(){ // // Get Errors // return fError; } //=========================================================================== std::string& TPCCommandCoderDB::getCoCoInfo(){ // // Get Information about Command Coder // return fVersion; } //=========================================================================== int32_t TPCCommandCoderDB::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 TPCCommandCoderDB instance; return &instance; }