ATLAS Offline Software
Loading...
Searching...
No Matches
LArRodBlockTransparentV0.icc
Go to the documentation of this file.
1//Dear emacs, this is -*- c++ -*-
2
3/*
4 Copyright (C) 2002-2026 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#ifdef LARBSDBGOUTPUT
15#define LARBSDBG(text) logstr<<MSG::DEBUG<<text<<endmsg
16#else
17#define LARBSDBG(text)
18#endif
19
20template<class DSPHEADER>
21LArRodBlockTransparentV0<DSPHEADER>::LArRodBlockTransparentV0(IMessageSvc* msgSvc)
22 : LArRodBlockStructure(msgSvc, BlockType())
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
31template<class DSPHEADER>
32void LArRodBlockTransparentV0<DSPHEADER>::clearBlocks()
33{
34 m_RawDataBlock.clear();
35}
36
37template<class DSPHEADER>
38void LArRodBlockTransparentV0<DSPHEADER>::resetPointers()
39{
40 m_RawDataCounter=0;
41 m_RawDataIndex=0;
42}
43
44template<class DSPHEADER>
45void LArRodBlockTransparentV0<DSPHEADER>::setNumberOfSamples(const uint8_t n)
46{ uint16_t value=getVectorHeader16(DSPHEADER::NSamples);
47 setHeader16(DSPHEADER::NSamples, (value & 0xff00) | n);
48}
49
50template<class DSPHEADER>
51void 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
56template<class DSPHEADER>
57uint8_t LArRodBlockTransparentV0<DSPHEADER>::getTDCPhase() const
58{
59 return (getHeader16(DSPHEADER::NSamples)>>8);
60}
61
62
63
64
65template<class DSPHEADER>
66void LArRodBlockTransparentV0<DSPHEADER>::setNumberOfGains(const uint8_t n)
67{
68 setHeader16(DSPHEADER::NGains,n);
69}
70
71template<class DSPHEADER>
72void
73LArRodBlockTransparentV0<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
99template<class DSPHEADER>
100void 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
109template<class DSPHEADER>
110void 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
134 // Save data as is, we will arrange it later...
135 m_RawDataBlock.push_back(channel);
136 if(channel>=64) { // high channel number on lower 16 bits
137 m_RawDataBlock.push_back(OfflineToRawGain(gain)<<12);
138 for (unsigned int i=0;i<nsamples;i++)
139 m_RawDataBlock.push_back(samples[i]&0xffff);
140 } else { //low channel number
141 m_RawDataBlock.push_back(OfflineToRawGain(gain)<<28);
142 for (unsigned int i=0;i<nsamples;i++)
143 m_RawDataBlock.push_back(samples[i]<<16);
144 }
145}
146
147template<class DSPHEADER>
148void LArRodBlockTransparentV0<DSPHEADER>::finalizeFEB()
149{
150#ifdef LARBSDBGOUTPUT
151 MsgStream logstr(Athena::getMessageSvc(), BlockType());
152#endif
153
154 uint16_t nsamples = getVectorHeader16(DSPHEADER::NSamples) & 0xff;
155 uint16_t ngains = 1;
156 uint16_t size = 0;
157 uint16_t s_size = 0;
158
159 // Set fragment size to FEB raw data + header
160 s_size = 8 + 64 * ngains; // Size of one sample block 16 RADD of 16 bit + 128 channels (16 bit data)
161 size = m_iHeadBlockSize + nsamples*s_size; // Total fragment size;
162
163 m_vFragment->resize(size,0);
164
165 LARBSDBG("Size of block (in 32bit words) = " << size);
166 // Now fill the RADD structures
167 for(int i=0; i<nsamples;i++) {
168 uint32_t offset = (m_iHeadBlockSize + i*s_size);
169 for(int j=0;j<8;j++) {
170 // Put a dummy code for RADDs (A | adc nb | sample nb)
171 uint32_t index = offset+j;
172 (*m_vFragment)[index] = 0xA000A000 | ((2*j)<<24) | (i << 16) | ((2*j+1)<<8) | i;
173 }
174 }
175 // And now the data itself
176 for (int igain=0;igain<ngains;igain++) {
177 int n = m_RawDataBlock.size();
178 for(int j=0; j<n;j+=nsamples+2) {
179 uint32_t ichannel = m_RawDataBlock[j];
180 uint32_t febgain = m_RawDataBlock[j+1];
181 uint32_t offset;
182 offset=m_iHeadBlockSize + 8 + ((ichannel&0x3F)>>3) + ((ichannel& 0x7)<<3) + 64*igain;
183 LARBSDBG("Processing channel #" << ichannel << ".Writing samples to offset " << offset);
184 for (int s=0;s<nsamples;s++) {
185 // samples are already on the right higher/lower bits of the 32 bit word
186 uint32_t index = offset + s*s_size;
187 uint32_t feb_data = (*m_vFragment)[index];
188 uint32_t sample = m_RawDataBlock[j+2+s];
189 feb_data = feb_data | sample | febgain;
190 (*m_vFragment)[index] = feb_data;
191 }
192 }
193 }
194 // Set header words
195 LARBSDBG("FINAL Nsamples= " << nsamples);
196 setHeader16(DSPHEADER::NGains,ngains);
197 setHeader32(DSPHEADER::RawDataBlkOffset, m_iHeadBlockSize);
198 setHeader32(DSPHEADER::NWTot,m_vFragment->size());
199 // clear memory
200 clearBlocks();
201 return;
202}
203
204template<class DSPHEADER>
205void LArRodBlockTransparentV0<DSPHEADER>::concatinateFEBs( )
206{
207 FEBMAPTYPE::const_iterator feb_it_b=m_mFebBlocks.begin();
208 FEBMAPTYPE::const_iterator feb_it_e=m_mFebBlocks.end();
209 FEBMAPTYPE::const_iterator feb_it;
210 for (feb_it=feb_it_b;feb_it!=feb_it_e;++feb_it) {
211 if (feb_it!=feb_it_b) //Not first Feb
212 m_pRODblock->resize( m_pRODblock->size()+m_MiddleHeaderSize);
213
214 //Add feb data to rod data block
215 for (uint32_t data : feb_it->second)
216 m_pRODblock->push_back(data);
217 } //end for feb_it
218
219 m_mFebBlocks.clear();
220 return;
221}
222
223template<class DSPHEADER>
224int LArRodBlockTransparentV0<DSPHEADER>::getNextRawData(int& channelNumber, std::vector<short>& samples, uint32_t& gain)
225{
226#ifdef LARBSDBGOUTPUT
227 MsgStream logstr(Athena::getMessageSvc(), BlockType());
228#endif
229 //Debug output
230 LARBSDBG("GetNextRawData for FEB 0x" << MSG::hex << (uint32_t)getHeader32(DSPHEADER::FEBID) << MSG::dec);
231 LARBSDBG("m_RawDataCounter=" << m_RawDataCounter << " m_RawDataIndex="<< m_RawDataIndex
232 << " m_channelsPerFEB=" << m_channelsPerFEB);
233 LARBSDBG("requested gain= " << m_fixedGain);
234 if (m_RawDataCounter>=m_channelsPerFEB) { //Already beyond maximal number of channels
235 LARBSDBG("Maximum number of channels reached");
236 return 0;
237 }
238 const uint16_t block = getHeader32(m_BlkOffset);//Position of the raw FEB data block
239 if (!block) { //Block does not exist
240 LARBSDBG("No Raw Data Block in this FEB");
241 return 0;
242 }
243 //The m_RawDataChannel keeps track of the last read channel
244
245 // Get next channel
246 channelNumber=m_RawDataCounter;
247 uint32_t febgain;
248 const unsigned int nsamples = getHeader16(DSPHEADER::NSamples) & 0xff;
249 const unsigned int ngains = getHeader16(DSPHEADER::NGains);
250 LARBSDBG("This FEB has " << nsamples << " samples");
251 LARBSDBG("This FEB has " << ngains << " gains");
252 if(ngains==0 || nsamples==0) return 0;
253 // Loop over gains to look for m_fixedGain
254 unsigned int this_gain=0;
255 int offset;
256 if (m_fixedGain!=CaloGain::LARNGAIN) { //Fixed gain: Search for gain
257 offset=block + 8 + ((channelNumber&0x3F)>>3) + ((channelNumber & 0x7)<<3);
258 for(this_gain=0;this_gain<ngains;this_gain++) {
259 int index = offset + 64*this_gain;
260 uint32_t x = m_FebBlock[index];
261 if(channelNumber>=64)
262 x = (x & 0x3000) >> 12;
263 else
264 x = (x & 0x30000000) >> 28;
265 int data_gain = RawToOfflineGain(x);
266 if(data_gain==m_fixedGain) break;
267 }
268 }
269 if (this_gain<ngains) { //Gain found in this fragment
270 int s_size = 8 + 64 * ngains; // Size of one sample block 16 RADD of 16 bit + 128 channels (16 bit data)
271 offset = block + 8 + ((channelNumber&0x3F)>>3) + ((channelNumber & 0x7)<<3) + 64*this_gain;
272 int index = offset;
273 uint32_t x = m_FebBlock[index];
274 if(channelNumber>=64) { //low channels on lower bits
275 // First decode gain
276 febgain = (x & 0x3000) >> 12; // gain on bits 12 and 13
277 // Than samples
278 for(unsigned int s=0;s<nsamples;s++) {
279 index = offset + s*s_size;
280 x = m_FebBlock[index];
281 samples.push_back((short) (x & 0x0fff)); // sample on bits 0 to 11
282 }
283 } else { //high channels on higher bits
284 // First decode gain
285 febgain = (x & 0x30000000) >> 28; // gain on bits 12 and 13
286 // Than samples
287 for(unsigned int s=0;s<nsamples;s++) {
288 index = offset + s*s_size;
289 x = (m_FebBlock[index]) >> 16;
290 samples.push_back((short) (x & 0x0fff)); // sample on bits 0 to 11
291 }
292 }
293 gain=RawToOfflineGain(febgain);
294 }
295 ++m_RawDataCounter;
296 if (m_rearrangeFirstSample && m_rearrangeFirstSample<samples.size()) //FIXME: Very ugly hack! See explanation in LArRodDecoder.h file
297 {//Change e.g. 3 0 1 2 4 to 0 1 2 3 4
298 short movedSample=samples[0];
299 for (unsigned i=1;i<=m_rearrangeFirstSample;i++)
300 samples[i-1]=samples[i];
301 samples[m_rearrangeFirstSample]=movedSample;
302 }
303 return 1;
304}
305
306template<class DSPHEADER>
307uint32_t LArRodBlockTransparentV0<DSPHEADER>::getNumberOfSamples() const
308{
309 return getHeader16(DSPHEADER::NSamples);
310}
311
312template<class DSPHEADER>
313uint32_t LArRodBlockTransparentV0<DSPHEADER>::getNumberOfGains() const
314{
315 return getHeader16(DSPHEADER::NGains);
316}
317
318template<class DSPHEADER>
319uint32_t LArRodBlockTransparentV0<DSPHEADER>::getRadd(uint32_t adc, uint32_t sample) const
320{
321 int ngain=getHeader16(DSPHEADER::NGains);
322 int index=getHeader32(m_BlkOffset);
323 index+=(8+64*ngain)*sample+adc/2;
324 uint32_t x=m_FebBlock[index];
325 if(adc&0x1) return x>>16;
326 return x&0xffff;
327}
328
329template<class DSPHEADER>
330uint16_t LArRodBlockTransparentV0<DSPHEADER>::getCtrl1(uint32_t adc) const
331{
332 int index=getHeader32(m_BlkOffset)-16+adc/2;
333 uint32_t x=m_FebBlock[index];
334 if(adc&0x1) x=x>>16;
335 else x=x&0xffff;
336 uint16_t ctrl=x;
337 return ctrl;
338}
339
340template<class DSPHEADER>
341uint16_t LArRodBlockTransparentV0<DSPHEADER>::getCtrl2(uint32_t adc) const
342{
343 int index=getHeader32(m_BlkOffset)-8+adc/2;
344 uint32_t x=m_FebBlock[index];
345 if(adc&0x1) x=x>>16;
346 else x=x&0xffff;
347 uint16_t ctrl=x;
348 return ctrl;
349}
350
351template<class DSPHEADER>
352uint16_t LArRodBlockTransparentV0<DSPHEADER>::getCtrl3(uint32_t adc) const
353{
354 int nsamples = getHeader16(DSPHEADER::NSamples);
355 int ngains = getHeader16(DSPHEADER::NGains);
356 int offset=nsamples*(8+64*ngains)+adc/2;
357 int index=getHeader32(m_BlkOffset)+offset;
358 uint32_t x=m_FebBlock[index];
359 if(adc&0x1) x=x>>16;
360 else x=x&0xffff;
361 uint16_t ctrl=x;
362 return ctrl;
363}
364
365template<class DSPHEADER>
366uint32_t LArRodBlockTransparentV0<DSPHEADER>::getStatus() const
367{
368 int nsamples = getHeader16(DSPHEADER::NSamples);
369 int ngains = getHeader16(DSPHEADER::NGains);
370 int offset=nsamples*(8+64*ngains)+8;
371 int index=getHeader32(m_BlkOffset)+offset;
372 uint32_t x=m_FebBlock[index];
373 return x;
374}
375
376
377#ifdef LARBSDBGOUTPUT
378#undef LARBSDBGOUTPUT
379#endif
380#undef LARBSDBG