#include "FecContainer.h" /* ===================================================================== * Container for the FEC Data block to configure one FEC. This can be * Board Controller registers plus (if needed) the registers of 8 Altros * on the FEC. The structure is: * * 1) FEE_CONFIGURE for FEC block, parameter = number of words * 2) HW_Address * 3) Checksum * * 4) Payload: Data for 1 FEC: * * - Board Controller Data * - Global and Channel Registers for 8 Altros * * * 5) FEE_VERIFICATION (FEC Block) * 6) CE_CMD_TAILER - End of FEE_VERIFICATION * * 7) FEE_CONFIGURE_END - End of FEE_CONFIGURE * 8) HW_Address, same as above * 9) CE_CMD_TAILER - End of FEE_CONFIGURE_END * * 10) CE_CMD_TAILER - End of FEE_CONFIGURE * ===================================================================== */ /* * Author: C. Lippmann, Christian.Lippmann@cern.ch */ //=========================================================================== FecContainer::FecContainer() { // Constructor reset(); fPayload.reserve(2500); fMaxSize = 0xffff; } //=========================================================================== FecContainer::FecContainer(uint32_t hardwareAddress) { // Constructor reset(); fHardwareAddress = hardwareAddress; fPayload.reserve(2500); fMaxSize = 0xffff; } //=========================================================================== FecContainer::~FecContainer() { // Destructor } //=========================================================================== void FecContainer::setAltroInstructionStore(bool store) { fStore = store; for ( uint32_t i=0; i<8; i++ ) fAltro[i].setAltroInstructionStore(store); } //=========================================================================== void FecContainer::reset() { // Reset all fHardwareAddress = 0; fConfigId = 0; fCheckSum = 0; fPayload.clear(); fVerif = false; fStore = false; for ( uint32_t i=0; i<8; i++ ) fAltro[i].reset(); //fTemporary.clear(); fSizeCounter = 0; } //=========================================================================== void FecContainer::setReadResult(bool read) { fRead = read; for ( uint32_t i=0; i<8; i++ ) fAltro[i].setReadResult(read); } //=========================================================================== void FecContainer::fillBc(uint32_t data) { // Fill Fec container with Board Controller register data, add a tailer fillBc(data, true); } //=========================================================================== void FecContainer::fillBc(uint32_t data, bool addTailer) { // Fill Fec container with Board Controller register data. // Choose if you wish a tailer added fPayload.push_back(data); if (addTailer) fPayload.push_back(fRCUce.sendCE_CMD_TAILER()); } //=========================================================================== void FecContainer::fillBc(uint64_t data) { // Fill Fec container with Board Controller register data, two 32bit words // Add a tailer fillBc(data, true); } //=========================================================================== void FecContainer::fillBc(uint64_t data, bool addTailer) { // Fill Fec container with Board Controller register data, two 32bit words // Choose if you wish a tailer added fPayload.push_back(data>>32); fPayload.push_back(data&0xFFFFFFFF); if (addTailer) fPayload.push_back(fRCUce.sendCE_CMD_TAILER()); // Tailer for this command (OK?) } //=========================================================================== void FecContainer::fillAltro(uint32_t altro, uint32_t data) { // Fill Altro container with register data if ( altro < 8 ) fAltro[altro].fill(data); } //=========================================================================== void FecContainer::fillAltro(uint32_t altro, uint64_t data) { // Fill Altro container with register data if ( altro < 8 ) fAltro[altro].fill(data); } //=========================================================================== void FecContainer::finalize() { // // Finalize the data block, including the header and tailer. // NOTE 1: Call this function only once! Otherwise you get each header and tailer twice! // NOTE 2: Calling getDataBlock() or size() before finalize() does not make sense! // uint32_t bsize = size(); if ( bsize > fMaxSize ) throw TpcException( (string) "FecContainer: Size of block too large."); if ( bsize > 0 ) { if ( fStore ) { fPayload.insert(fPayload.begin(), fRCUce.sendRCU_ALTRO_INSTRUCTION_STORE(bsize)); fPayload.push_back(fRCUce.sendCE_CMD_TAILER()); // ends RCU_ALTRO_INSTRUCTION_STORE } else { fPayload.push_back(fRCU.sendEND()); // RCU_END bsize++; fPayload.insert(fPayload.begin(), fRCUce.sendRCU_EXEC_INSTRUCTION(bsize)); fPayload.push_back(fRCUce.sendCE_CMD_TAILER()); // ends RCU_EXEC_INSTRUCTION } } // Add ALTRO data uint32_t *mem = 0; try { for (uint32_t i=0; i<8; i++) { // Get and add ALTRO blocks if ( fAltro[i].empty() ) continue; // this container is empty fAltro[i].setHardwareAddress(fHardwareAddress + (i<<4)); fAltro[i].finalize(); mem = fAltro[i].getDataBlock(); fPayload.insert(fPayload.end(), mem, mem+fAltro[i].size()); } } catch (TpcException ea) { throw TpcException( (string) ea.what()); } // Add headers if (fVerif) fPayload.push_back(fRCUce.sendFEE_VERIFICATION()); // if (fVerif) fPayload.push_back(fRCUce.sendCE_CMD_TAILER()); // ends FEE_VERIFICATION if (fRead) fPayload.push_back(fRCUce.sendFEE_CONFIGURE_END_NOSTATE()); else fPayload.push_back(fRCUce.sendFEE_CONFIGURE_END()); fPayload.push_back(fRCUce.sendFEE_CONFIGURE_END_1Word(fConfigId, fRCUce.deviceFEC(), fHardwareAddress)); fPayload.push_back(fRCUce.sendCE_CMD_TAILER()); // ends FEE_CONFIGURE_END bsize = size(); fPayload.insert(fPayload.begin(), fCheckSum); fPayload.insert(fPayload.begin(), fRCUce.sendFEE_CONFIGURE_1Word(fConfigId, fRCUce.deviceFEC(), fHardwareAddress)); if (fRead) fPayload.insert(fPayload.begin(), fRCUce.sendFEE_CONFIGURE_NOSTATE(bsize)); else fPayload.insert(fPayload.begin(), fRCUce.sendFEE_CONFIGURE(bsize)); fPayload.push_back(fRCUce.sendCE_CMD_TAILER()); // ends FEE_CONFIGURE } //=========================================================================== uint32_t* FecContainer::getDataBlock() { // // Return the data block, including the header and tailer. // return &fPayload[0]; } //=========================================================================== void FecContainer::CalculateCheckSum() { // To be implemented fCheckSum = 0; } //=========================================================================== bool FecContainer::empty() { // Is there some data ? if (size() > 0) return false; for (uint32_t i=0; i<8; i++) { if ( !fAltro[i].empty() ) return false; } return true; }