1 //Dear emacs, this is -*- c++ -*-
4 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
7 // Implementation of a LArRODBlockStructure class
8 // This version contains LArDigits in fixed gain.
9 // See .h file for more details.
11 #include "AthenaKernel/getMessageSvc.h"
14 //#define LARBSDBGOUTPUT
16 #define LARBSDBG(text) logstr<<MSG::DEBUG<<text<<endmsg
18 #define LARBSDBG(text)
21 template<class DSPHEADER>
22 LArRodBlockTransparentV0<DSPHEADER>::LArRodBlockTransparentV0() : LArRodBlockStructure()
23 { m_iHeadBlockSize=DSPHEADER::endtag/2; // The implicit cast rounds down to the right size
24 //Fill array of offset to enable for-loops
25 m_BlkOffset=DSPHEADER::RawDataBlkOffset; //RawDataOffset
26 m_fixedGain=CaloGain::LARNGAIN;
27 LArRodBlockTransparentV0::resetPointers();
30 // clear temporary block vectors
31 template<class DSPHEADER>
32 void LArRodBlockTransparentV0<DSPHEADER>::clearBlocks()
34 m_RawDataBlock.clear();
37 template<class DSPHEADER>
38 void LArRodBlockTransparentV0<DSPHEADER>::resetPointers()
44 template<class DSPHEADER>
45 void LArRodBlockTransparentV0<DSPHEADER>::setNumberOfSamples(const uint8_t n)
46 { uint16_t value=getVectorHeader16(DSPHEADER::NSamples);
47 setHeader16(DSPHEADER::NSamples, (value & 0xff00) | n);
50 template<class DSPHEADER>
51 void LArRodBlockTransparentV0<DSPHEADER>::setTDCPhase(const uint8_t n)
52 { uint16_t value=getVectorHeader16(DSPHEADER::NSamples);
53 setHeader16(DSPHEADER::NSamples, (value & 0xff) | ((uint16_t) n<<8));
56 template<class DSPHEADER>
57 uint8_t LArRodBlockTransparentV0<DSPHEADER>::getTDCPhase() const
59 return (getHeader16(DSPHEADER::NSamples)>>8);
65 template<class DSPHEADER>
66 void LArRodBlockTransparentV0<DSPHEADER>::setNumberOfGains(const uint8_t n)
68 setHeader16(DSPHEADER::NGains,n);
71 template<class DSPHEADER>
73 LArRodBlockTransparentV0<DSPHEADER>::initializeFragment(std::vector<uint32_t>& fragment)
74 {MsgStream logstr(Athena::getMessageSvc(), BlockType());
75 m_pRODblock=&fragment; //remember pointer to fragment
76 if (fragment.size()>m_iHeadBlockSize) { //Got filled fragment
77 unsigned int sizeRead=0;
78 //Store existing data in the FEB-Map
79 while (sizeRead<fragment.size()) {
80 std::vector<uint32_t>::iterator FebIter;
81 FebIter=fragment.begin()+sizeRead; //Store pointer to current Feb-Header
82 m_FebBlock=&(*FebIter); //Set m_FebBlock in order to use getHeader-functions.
83 uint32_t currFEBid=getHeader32(DSPHEADER::FEBID); //Get this FEB-ID
84 uint16_t currFebSize=getHeader32(DSPHEADER::NWTot); //Size of this FEB-Block
85 if (FebIter+currFebSize>fragment.end()) {
86 fragment.clear(); //Clear existing vector
87 logstr << MSG::ERROR << "initializeFragment: Got inconsistent ROD-Fragment!" << endmsg;
90 m_mFebBlocks[currFEBid].assign(FebIter,FebIter+currFebSize); //Copy data from ROD-fragment into FEB-Block
91 sizeRead+=currFebSize+m_MiddleHeaderSize;
92 LARBSDBG("Found FEB-id "<< currFEBid << "in existing ROD-Fragment");
95 fragment.clear(); //Clear existing vector
99 template<class DSPHEADER>
100 void LArRodBlockTransparentV0<DSPHEADER>::initializeFEB(const uint32_t id)
101 {m_vFragment=&(m_mFebBlocks[id]);
102 //m_FebHeaderIter=m_vFragment->begin();
103 if (m_vFragment->size()<m_iHeadBlockSize) //Got empty or spoiled fragment
104 {m_vFragment->resize(m_iHeadBlockSize,0); //Initialize FEB-Header
105 setHeader32(DSPHEADER::FEBID,id); //Set Feb ID
109 template<class DSPHEADER>
110 void LArRodBlockTransparentV0<DSPHEADER>::setRawDataFixed(const int channel, const std::vector<short>& samples, const uint32_t gain)
112 MsgStream logstr(Athena::getMessageSvc(), BlockType());
113 if (channel>=m_channelsPerFEB) {
114 logstr << MSG::ERROR << "Attempt to write Raw Data for channel "<< channel << endmsg;
115 return; //Return error
117 // Expected Gain values:
122 {logstr << MSG::ERROR << "Attempt to write raw data with gain "<< gain << endmsg;
125 unsigned int nsamples = getVectorHeader16(DSPHEADER::NSamples) & 0xff;
126 LARBSDBG("Nsamples= " << nsamples);
127 if(samples.size() != nsamples) {
128 logstr << MSG::ERROR << "Number of samples mismatch!\n";
129 logstr << " nsamples =" << nsamples;
130 logstr << " samples.size() =" << samples.size() << endmsg;
133 //std::cout << "Size of Raw Data block # " << febgain << " = " << m_RawDataBlock.size();
138 // Save data as is, we will arrange it later...
139 m_RawDataBlock.push_back(channel);
140 if(channel>=64) { // high channel number on lower 16 bits
141 m_RawDataBlock.push_back(OfflineToRawGain(gain)<<12);
142 for (unsigned int i=0;i<nsamples;i++)
143 m_RawDataBlock.push_back(samples[i]&0xffff);
144 } else { //low channel number
145 m_RawDataBlock.push_back(OfflineToRawGain(gain)<<28);
146 for (unsigned int i=0;i<nsamples;i++)
147 m_RawDataBlock.push_back(samples[i]<<16);
151 template<class DSPHEADER>
152 void LArRodBlockTransparentV0<DSPHEADER>::finalizeFEB()
154 #ifdef LARBSDBGOUTPUT
155 MsgStream logstr(Athena::getMessageSvc(), BlockType());
158 uint16_t nsamples = getVectorHeader16(DSPHEADER::NSamples) & 0xff;
163 // Set fragment size to FEB raw data + header
164 s_size = 8 + 64 * ngains; // Size of one sample block 16 RADD of 16 bit + 128 channels (16 bit data)
165 size = m_iHeadBlockSize + nsamples*s_size; // Total fragment size;
167 //m_vFragment->resize( m_iHeadBlockSize);
168 m_vFragment->resize(size,0);
170 LARBSDBG("Size of block (in 32bit words) = " << size);
171 // Now fill the RADD structures
172 for(int i=0; i<nsamples;i++) {
173 uint32_t offset = (m_iHeadBlockSize + i*s_size);
174 for(int j=0;j<8;j++) {
175 // Put a dummy code for RADDs (A | adc nb | sample nb)
176 uint32_t index = offset+j;
177 (*m_vFragment)[index] = 0xA000A000 | ((2*j)<<24) | (i << 16) | ((2*j+1)<<8) | i;
180 // And now the data itself
181 for (int igain=0;igain<ngains;igain++) {
182 int n = m_RawDataBlock.size();
183 for(int j=0; j<n;j+=nsamples+2) {
184 uint32_t ichannel = m_RawDataBlock[j];
185 uint32_t febgain = m_RawDataBlock[j+1];
187 offset=m_iHeadBlockSize + 8 + ((ichannel&0x3F)>>3) + ((ichannel& 0x7)<<3) + 64*igain;
188 LARBSDBG("Processing channel #" << ichannel << ".Writing samples to offset " << offset);
189 for (int s=0;s<nsamples;s++) {
190 // samples are already on the right higher/lower bits of the 32 bit word
191 uint32_t index = offset + s*s_size;
192 uint32_t feb_data = (*m_vFragment)[index];
193 uint32_t sample = m_RawDataBlock[j+2+s];
194 feb_data = feb_data | sample | febgain;
195 (*m_vFragment)[index] = feb_data;
200 LARBSDBG("FINAL Nsamples= " << nsamples);
201 //setHeader16(DSPHEADER::NSamples,nsamples);
202 //setNumberOfSamples(nsamples);
203 setHeader16(DSPHEADER::NGains,ngains);
204 setHeader32(DSPHEADER::RawDataBlkOffset, m_iHeadBlockSize);
205 setHeader32(DSPHEADER::NWTot,m_vFragment->size());
211 template<class DSPHEADER>
212 void LArRodBlockTransparentV0<DSPHEADER>::concatinateFEBs( )
214 // std::cout << "Concatinating FEBs. Have "<< m_mFebBlocks.size() <<" febs." << std::endl;
215 FEBMAPTYPE::const_iterator feb_it_b=m_mFebBlocks.begin();
216 FEBMAPTYPE::const_iterator feb_it_e=m_mFebBlocks.end();
217 FEBMAPTYPE::const_iterator feb_it;
218 for (feb_it=feb_it_b;feb_it!=feb_it_e;++feb_it) {
219 if (feb_it!=feb_it_b) //Not first Feb
221 if (fullHeader) {//Add middle header
222 m_pRODblock->push_back(fullHeader->version().full());//Format Version number
223 m_pRODblock->push_back(fullHeader->source_id()); //Source identifer
224 m_pRODblock->push_back(fullHeader->run_no());
225 m_pRODblock->push_back(fullHeader->lvl1_id()); //Level 1 identifer
226 m_pRODblock->push_back(fullHeader->bc_id()); //Bunch Crossing identifer
227 m_pRODblock->push_back(fullHeader->lvl1_type()); //Level 1 trigger type
228 m_pRODblock->push_back(fullHeader->detev_type()); //Detector event type
232 m_pRODblock->resize( m_pRODblock->size()+m_MiddleHeaderSize);
234 //Add feb data to rod data block
235 for (uint32_t data : feb_it->second)
236 m_pRODblock->push_back(data);
239 m_mFebBlocks.clear();
243 template<class DSPHEADER>
244 int LArRodBlockTransparentV0<DSPHEADER>::getNextRawData(int& channelNumber, std::vector<short>& samples, uint32_t& gain)
246 #ifdef LARBSDBGOUTPUT
247 MsgStream logstr(Athena::getMessageSvc(), BlockType());
250 LARBSDBG("GetNextRawData for FEB 0x" << MSG::hex << (uint32_t)getHeader32(DSPHEADER::FEBID) << MSG::dec);
251 LARBSDBG("m_RawDataCounter=" << m_RawDataCounter << " m_RawDataIndex="<< m_RawDataIndex
252 << " m_channelsPerFEB=" << m_channelsPerFEB);
253 LARBSDBG("requested gain= " << m_fixedGain);
254 if (m_RawDataCounter>=m_channelsPerFEB) { //Already beyond maximal number of channels
255 LARBSDBG("Maximum number of channels reached");
258 const uint16_t block = getHeader32(m_BlkOffset);//Position of the raw FEB data block
259 if (!block) { //Block does not exist
260 LARBSDBG("No Raw Data Block in this FEB");
263 //The m_RawDataChannel keeps track of the last read channel
264 //std::cout << "endtag=" << DSPHEADER::endtag << " m_iHeadBlockSize=" << m_iHeadBlockSize << std::endl;
267 channelNumber=m_RawDataCounter;
269 const unsigned int nsamples = getHeader16(DSPHEADER::NSamples) & 0xff;
270 const unsigned int ngains = getHeader16(DSPHEADER::NGains);
271 LARBSDBG("This FEB has " << nsamples << " samples");
272 LARBSDBG("This FEB has " << ngains << " gains");
273 if(ngains==0 || nsamples==0) return 0;
274 // Loop over gains to look for m_fixedGain
275 unsigned int this_gain=0;
277 if (m_fixedGain!=CaloGain::LARNGAIN) { //Fixed gain: Search for gain
278 offset=block + 8 + ((channelNumber&0x3F)>>3) + ((channelNumber & 0x7)<<3);
279 for(this_gain=0;this_gain<ngains;this_gain++) {
280 int index = offset + 64*this_gain;
281 uint32_t x = m_FebBlock[index];
282 if(channelNumber>=64)
283 x = (x & 0x3000) >> 12;
285 x = (x & 0x30000000) >> 28;
286 int data_gain = RawToOfflineGain(x);
287 if(data_gain==m_fixedGain) break;
290 if (this_gain<ngains) { //Gain found in this fragment
291 int s_size = 8 + 64 * ngains; // Size of one sample block 16 RADD of 16 bit + 128 channels (16 bit data)
292 offset = block + 8 + ((channelNumber&0x3F)>>3) + ((channelNumber & 0x7)<<3) + 64*this_gain;
294 uint32_t x = m_FebBlock[index];
295 if(channelNumber>=64) { //low channels on lower bits
297 febgain = (x & 0x3000) >> 12; // gain on bits 12 and 13
299 for(unsigned int s=0;s<nsamples;s++) {
300 index = offset + s*s_size;
301 x = m_FebBlock[index];
302 samples.push_back((short) (x & 0x0fff)); // sample on bits 0 to 11
304 } else { //high channels on higher bits
306 febgain = (x & 0x30000000) >> 28; // gain on bits 12 and 13
308 for(unsigned int s=0;s<nsamples;s++) {
309 index = offset + s*s_size;
310 x = (m_FebBlock[index]) >> 16;
311 samples.push_back((short) (x & 0x0fff)); // sample on bits 0 to 11
314 gain=RawToOfflineGain(febgain);
316 //std::cout << "Gain= " << gain << " Febgain=" << febgain << std::endl;
318 if (m_rearrangeFirstSample && m_rearrangeFirstSample<samples.size()) //FIXME: Very ugly hack! See explanation in LArRodDecoder.h file
319 {//Change e.g. 3 0 1 2 4 to 0 1 2 3 4
320 short movedSample=samples[0];
321 for (unsigned i=1;i<=m_rearrangeFirstSample;i++)
322 samples[i-1]=samples[i];
323 samples[m_rearrangeFirstSample]=movedSample;
328 template<class DSPHEADER>
329 uint32_t LArRodBlockTransparentV0<DSPHEADER>::getNumberOfSamples() const
331 return getHeader16(DSPHEADER::NSamples);
334 template<class DSPHEADER>
335 uint32_t LArRodBlockTransparentV0<DSPHEADER>::getNumberOfGains() const
337 return getHeader16(DSPHEADER::NGains);
340 template<class DSPHEADER>
341 uint32_t LArRodBlockTransparentV0<DSPHEADER>::getRadd(uint32_t adc, uint32_t sample) const
343 int ngain=getHeader16(DSPHEADER::NGains);
344 int index=getHeader32(m_BlkOffset);
345 index+=(8+64*ngain)*sample+adc/2;
346 uint32_t x=m_FebBlock[index];
347 if(adc&0x1) return x>>16;
351 template<class DSPHEADER>
352 uint16_t LArRodBlockTransparentV0<DSPHEADER>::getCtrl1(uint32_t adc) const
354 int index=getHeader32(m_BlkOffset)-16+adc/2;
355 uint32_t x=m_FebBlock[index];
362 template<class DSPHEADER>
363 uint16_t LArRodBlockTransparentV0<DSPHEADER>::getCtrl2(uint32_t adc) const
365 int index=getHeader32(m_BlkOffset)-8+adc/2;
366 uint32_t x=m_FebBlock[index];
373 template<class DSPHEADER>
374 uint16_t LArRodBlockTransparentV0<DSPHEADER>::getCtrl3(uint32_t adc) const
376 int nsamples = getHeader16(DSPHEADER::NSamples);
377 int ngains = getHeader16(DSPHEADER::NGains);
378 int offset=nsamples*(8+64*ngains)+adc/2;
379 int index=getHeader32(m_BlkOffset)+offset;
380 uint32_t x=m_FebBlock[index];
387 template<class DSPHEADER>
388 uint32_t LArRodBlockTransparentV0<DSPHEADER>::getStatus() const
390 int nsamples = getHeader16(DSPHEADER::NSamples);
391 int ngains = getHeader16(DSPHEADER::NGains);
392 int offset=nsamples*(8+64*ngains)+8;
393 int index=getHeader32(m_BlkOffset)+offset;
394 uint32_t x=m_FebBlock[index];
399 #ifdef LARBSDBGOUTPUT
400 #undef LARBSDBGOUTPUT