ATLAS Offline Software
LArRodBlockTransparentV0.icc
Go to the documentation of this file.
1 //Dear emacs, this is -*- c++ -*-
2 
3 /*
4  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
5 */
6 
7 // Implementation of a LArRODBlockStructure class
8 // This version contains LArDigits in fixed gain.
9 // See .h file for more details.
10 
11 #include "AthenaKernel/getMessageSvc.h"
12 #include <iostream>
13 
14 //#define LARBSDBGOUTPUT
15 #ifdef LARBSDBGOUTPUT
16 #define LARBSDBG(text) logstr<<MSG::DEBUG<<text<<endmsg
17 #else
18 #define LARBSDBG(text)
19 #endif
20 
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();
28 }
29 
30 // clear temporary block vectors
31 template<class DSPHEADER>
32 void LArRodBlockTransparentV0<DSPHEADER>::clearBlocks()
33 {
34  m_RawDataBlock.clear();
35 }
36 
37 template<class DSPHEADER>
38 void LArRodBlockTransparentV0<DSPHEADER>::resetPointers()
39 {
40  m_RawDataCounter=0;
41  m_RawDataIndex=0;
42 }
43 
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);
48 }
49 
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));
54 }
55 
56 template<class DSPHEADER>
57 uint8_t LArRodBlockTransparentV0<DSPHEADER>::getTDCPhase() const
58 {
59  return (getHeader16(DSPHEADER::NSamples)>>8);
60 }
61 
62 
63 
64 
65 template<class DSPHEADER>
66 void LArRodBlockTransparentV0<DSPHEADER>::setNumberOfGains(const uint8_t n)
67 {
68  setHeader16(DSPHEADER::NGains,n);
69 }
70 
71 template<class DSPHEADER>
72 void
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;
88  return;
89  }
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");
93  } // end while
94  }
95  fragment.clear(); //Clear existing vector
96  return;
97 }
98 
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
106  }
107 }
108 
109 template<class DSPHEADER>
110 void LArRodBlockTransparentV0<DSPHEADER>::setRawDataFixed(const int channel, const std::vector<short>& samples, const uint32_t gain)
111 {
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
116  }
117  // Expected Gain values:
118  //0..high gain
119  //1..medium gain
120  //2..low gain
121  if (gain>2)
122  {logstr << MSG::ERROR << "Attempt to write raw data with gain "<< gain << endmsg;
123  return;
124  }
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;
131  std::abort();
132  }
133  //std::cout << "Size of Raw Data block # " << febgain << " = " << m_RawDataBlock.size();
134 
135  // m_RawDataBlock
136 
137 
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);
148  }
149 }
150 
151 template<class DSPHEADER>
152 void LArRodBlockTransparentV0<DSPHEADER>::finalizeFEB()
153 {
154 #ifdef LARBSDBGOUTPUT
155  MsgStream logstr(Athena::getMessageSvc(), BlockType());
156 #endif
157 
158  uint16_t nsamples = getVectorHeader16(DSPHEADER::NSamples) & 0xff;
159  uint16_t ngains = 1;
160  uint16_t size = 0;
161  uint16_t s_size = 0;
162 
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;
166 
167  //m_vFragment->resize( m_iHeadBlockSize);
168  m_vFragment->resize(size,0);
169 
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;
178  }
179  }
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];
186  uint32_t offset;
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;
196  }
197  }
198  }
199  // Set header words
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());
206  // clear memory
207  clearBlocks();
208  return;
209 }
210 
211 template<class DSPHEADER>
212 void LArRodBlockTransparentV0<DSPHEADER>::concatinateFEBs( )
213 {
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
220 /*
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
229  }
230  else //No ROD-Header
231 */
232  m_pRODblock->resize( m_pRODblock->size()+m_MiddleHeaderSize);
233 
234  //Add feb data to rod data block
235  for (uint32_t data : feb_it->second)
236  m_pRODblock->push_back(data);
237  } //end for feb_it
238 
239  m_mFebBlocks.clear();
240  return;
241 }
242 
243 template<class DSPHEADER>
244 int LArRodBlockTransparentV0<DSPHEADER>::getNextRawData(int& channelNumber, std::vector<short>& samples, uint32_t& gain)
245 {
246 #ifdef LARBSDBGOUTPUT
247  MsgStream logstr(Athena::getMessageSvc(), BlockType());
248 #endif
249  //Debug output
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");
256  return 0;
257  }
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");
261  return 0;
262  }
263  //The m_RawDataChannel keeps track of the last read channel
264  //std::cout << "endtag=" << DSPHEADER::endtag << " m_iHeadBlockSize=" << m_iHeadBlockSize << std::endl;
265 
266  // Get next channel
267  channelNumber=m_RawDataCounter;
268  uint32_t febgain;
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;
276  int offset;
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;
284  else
285  x = (x & 0x30000000) >> 28;
286  int data_gain = RawToOfflineGain(x);
287  if(data_gain==m_fixedGain) break;
288  }
289  }
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;
293  int index = offset;
294  uint32_t x = m_FebBlock[index];
295  if(channelNumber>=64) { //low channels on lower bits
296  // First decode gain
297  febgain = (x & 0x3000) >> 12; // gain on bits 12 and 13
298  // Than samples
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
303  }
304  } else { //high channels on higher bits
305  // First decode gain
306  febgain = (x & 0x30000000) >> 28; // gain on bits 12 and 13
307  // Than samples
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
312  }
313  }
314  gain=RawToOfflineGain(febgain);
315  }
316  //std::cout << "Gain= " << gain << " Febgain=" << febgain << std::endl;
317  ++m_RawDataCounter;
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;
324  }
325  return 1;
326 }
327 
328 template<class DSPHEADER>
329 uint32_t LArRodBlockTransparentV0<DSPHEADER>::getNumberOfSamples() const
330 {
331  return getHeader16(DSPHEADER::NSamples);
332 }
333 
334 template<class DSPHEADER>
335 uint32_t LArRodBlockTransparentV0<DSPHEADER>::getNumberOfGains() const
336 {
337  return getHeader16(DSPHEADER::NGains);
338 }
339 
340 template<class DSPHEADER>
341 uint32_t LArRodBlockTransparentV0<DSPHEADER>::getRadd(uint32_t adc, uint32_t sample) const
342 {
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;
348  return x&0xffff;
349 }
350 
351 template<class DSPHEADER>
352 uint16_t LArRodBlockTransparentV0<DSPHEADER>::getCtrl1(uint32_t adc) const
353 {
354  int index=getHeader32(m_BlkOffset)-16+adc/2;
355  uint32_t x=m_FebBlock[index];
356  if(adc&0x1) x=x>>16;
357  else x=x&0xffff;
358  uint16_t ctrl=x;
359  return ctrl;
360 }
361 
362 template<class DSPHEADER>
363 uint16_t LArRodBlockTransparentV0<DSPHEADER>::getCtrl2(uint32_t adc) const
364 {
365  int index=getHeader32(m_BlkOffset)-8+adc/2;
366  uint32_t x=m_FebBlock[index];
367  if(adc&0x1) x=x>>16;
368  else x=x&0xffff;
369  uint16_t ctrl=x;
370  return ctrl;
371 }
372 
373 template<class DSPHEADER>
374 uint16_t LArRodBlockTransparentV0<DSPHEADER>::getCtrl3(uint32_t adc) const
375 {
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];
381  if(adc&0x1) x=x>>16;
382  else x=x&0xffff;
383  uint16_t ctrl=x;
384  return ctrl;
385 }
386 
387 template<class DSPHEADER>
388 uint32_t LArRodBlockTransparentV0<DSPHEADER>::getStatus() const
389 {
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];
395  return x;
396 }
397 
398 
399 #ifdef LARBSDBGOUTPUT
400 #undef LARBSDBGOUTPUT
401 #endif
402 #undef LARBSDBG