ATLAS Offline Software
Loading...
Searching...
No Matches
ZdcByteStreamReadV1V2Tool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5// ===========================================================================
6// Includes
7// ===========================================================================
8// STD:
9// ===========================================================================
10#include <stdexcept>
11#include <bitset>
12#include <iomanip>
13// ===========================================================================
14
15#include "eformat/SourceIdentifier.h"
18
19// PAS all adapted from L1Calo, since they hide all of their headers in "src"{!!}
25#include "ZdcByteStream/ZdcL1CaloSubBlock.h" // Only for error codes
28
31
33
34// ===========================================================================
35
36
37
38
39namespace {
40 constexpr int slink2ppmChannel[64] =
41 {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60,
42 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63,
43 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61,
44 2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62 };
45
46 uint32_t bitFieldSize(uint32_t word, uint8_t offset, uint8_t size) {
47 return (word >> offset) & ((1U << size) - 1);
48 }
49
50 uint32_t coolId(uint8_t crate, uint8_t module, uint8_t channel) {
51 const uint8_t pin = channel % 16;
52 const uint8_t asic = channel / 16;
53 return (crate << 24) | (1 << 20) | (module << 16) | (pin << 8) | asic;
54 }
55
56 int16_t pedCorrection(uint16_t twoBytePedCor) {
57 return twoBytePedCor > 511? (twoBytePedCor - 1024): twoBytePedCor;
58 }
59
60#if 0
61 std::string noAuxSuffix(const std::string& name) {
62 if ((name.size() > 4) && (name.substr(name.size()-4, 4) == "Aux.")) {
63 return name.substr(0, name.size() - 4);
64 }
65 return name;
66 }
67#endif
68}
69// namespace removed since I was not planning on putting everything into the LVL1BS namespace (yet)
70// ===========================================================================
71//namespace LVL1BS {
72// ===========================================================================
73// Constructor
75 "ZdcByteStreamxAODReadTool"*/) :
76 AsgTool(name),
77 m_errorTool("ZdcL1CaloErrorByteStreamTool/ZdcL1CaloErrorByteStreamTool"),
78 //m_ppmMaps("LVL1::PpmMappingTool/PpmMappingTool"),
79 m_robDataProvider("ROBDataProviderSvc", name) {
80 declareInterface<ZdcByteStreamReadV1V2Tool>(this);
81 //declareProperty("PpmMappingTool", m_ppmMaps,
82 // "Crate/Module/Channel to Eta/Phi/Layer mapping tool");
83 declareProperty("ROBDataProviderSvc", m_robDataProvider,
84 "Get ROB source IDs service");
85}
86
87// ===========================================================================
88// Initialize
89
90
92
93 m_srcIdMap = new ZdcSrcIdMap();
94 CHECK(m_errorTool.retrieve());
95 //CHECK(m_ppmMaps.retrieve());
96 CHECK(m_robDataProvider.retrieve());
97
98 const ZdcID* zdcID = nullptr;
99 if (detStore()->retrieve( zdcID ).isFailure() ) {
100 msg(MSG::ERROR) << "execute: Could not retrieve ZdcID object from the detector store" << endmsg;
101 return StatusCode::FAILURE;
102 }
103 else {
104 msg(MSG::DEBUG) << "execute: retrieved ZdcID" << endmsg;
105 }
106 m_zdcID = zdcID;
107
109
110 return StatusCode::SUCCESS;
111}
112// ===========================================================================
113// Finalize
114
116 delete m_srcIdMap;
117
118 return StatusCode::SUCCESS;
119}
120
121// Conversion bytestream to trigger towers
123 const IROBDataProviderSvc::VROBFRAG& robFrags,
124 xAOD::TriggerTowerContainer* const ttCollection) const
125{
126 State state;
127 state.m_subDetectorID = eformat::FORWARD_ZDC;
128 state.m_triggerTowers = ttCollection;
129
130 ROBIterator rob = robFrags.begin();
131 ROBIterator robEnd = robFrags.end();
132
133 int robCounter = 1;
134 for (; rob != robEnd; ++rob, ++robCounter) {
135 StatusCode sc = processRobFragment_(state, rob, RequestType::PPM);
136 if (!sc.isSuccess()) {
137
138 }
139 }
140 return StatusCode::SUCCESS;
141}
142
143// Conversion bytestream to trigger towers and then to ZDC digits
145 const IROBDataProviderSvc::VROBFRAG& robFrags,
146 ZdcDigitsCollection* zdcCollection) const
147{
148
151 ttCollection->setStore(aux);
152
153 ATH_MSG_DEBUG("Getting TT collection!");
154 StatusCode sc = convert(robFrags,ttCollection);
155
156 ATH_MSG_DEBUG("Got it!");
157
158 if (sc != StatusCode::SUCCESS) {
159 ATH_MSG_DEBUG("ZDC TT Conversion failed");
160 return sc;
161 }
162
163 ATH_MSG_DEBUG("convertTT2ZD");
164 //convertTT2ZD 'new-s' and returns a bare ptr for ZdcDigitsCollection...
165 //return by value or a unique_ptr would be safer
166 ZdcDigitsCollection* zc = convertTT2ZD(ttCollection);
167 ATH_MSG_DEBUG("convertedTT2ZD! Now copying");
168 (*zdcCollection) = (*zc);
169 //...so zc should be deleted
170 delete zc;
171 ATH_MSG_DEBUG("Copied!");
172
173 return StatusCode::SUCCESS;
174}
175
177 xAOD::TriggerTowerContainer* const ttCollection) const {
178 //return convert(LVL1::TrigT1CaloDefs::xAODTriggerTowerLocation, ttCollection);
179 return convert("ZdcTriggerTowerContainer", ttCollection);
180}
181
182StatusCode ZdcByteStreamReadV1V2Tool::convert(const std::string& sgKey,
183 xAOD::TriggerTowerContainer* const ttCollection) const {
184
185 //std::cout << "convert " << sgKey << std::endl;
186
187 const std::vector<uint32_t>& vID(ppmSourceIDs(sgKey));
188
189 // // get ROB fragments
191 m_robDataProvider->getROBData(Gaudi::Hive::currentContext(), vID, robFrags, "ZdcByteStreamxAODReadTool");
192 ATH_MSG_DEBUG("Number of ROB fragments:" << robFrags.size());
193
194 CHECK(convert(robFrags, ttCollection));
195 return StatusCode::SUCCESS;
196}
197
198// ===========================================================================
200 State& state,
201 const ROBIterator& robIter, const RequestType& /*requestedType*/) const {
202
203 auto rob = **robIter;
204
206 "Treating ROB fragment source id #" << MSG::hex << rob.rob_source_id());
207
208
209 state.m_rodSourceId = rob.rod_source_id();
210 state.m_robSourceId = rob.source_id();
211 const auto sourceID = (state.m_rodSourceId >> 16) & 0xff;
212 const auto rodCrate = ZdcSrcIdMap::crate(state.m_rodSourceId);
213 const auto rodSlink = ZdcSrcIdMap::slink(state.m_rodSourceId);
214 // -------------------------------------------------------------------------
215 // Check Rob status
216 if (rob.nstatus() > 0) {
217 ROBPointer robData;
218 rob.status(robData);
219 if (*robData != 0) {
220 ATH_MSG_WARNING("ROB status error - skipping fragment");
221 m_errorTool->robError(state.m_rodSourceId, *robData);
222 return StatusCode::FAILURE;
223 }
224 }
225 // -------------------------------------------------------------------------
226 RODPointer payloadBeg;
227 RODPointer payloadEnd;
228 RODPointer payload;
229
230 rob.rod_data(payloadBeg);
231 payloadEnd = payloadBeg + rob.rod_ndata();
232 payload = payloadBeg;
233 // -------------------------------------------------------------------------
234 if (payload == payloadEnd) {
235 ATH_MSG_DEBUG("ROB fragment empty");
236 return StatusCode::FAILURE;
237 }
238 // -------------------------------------------------------------------------
239
240
241 uint16_t rodVer = rob.rod_version() & 0xffff;
242 state.m_verCode = ((rodVer & 0xfff) << 4) | 1;
243 uint32_t rodRunNumber = rob.rod_run_no() & 0xffffff;
244
245
246 if (sourceID != state.m_subDetectorID) {
247 ATH_MSG_ERROR("Wrong subdetector source id for requested objects: " << state.m_rodSourceId);
248 return StatusCode::FAILURE;
249 }
250
251 ATH_MSG_DEBUG("Treating crate " << rodCrate << " slink " << rodSlink);
252
253 state.m_caloUserHeader = ZdcCaloUserHeader(*payload);
254 if (!state.m_caloUserHeader.isValid()) {
255 ATH_MSG_ERROR("Invalid or missing user header");
256 return StatusCode::FAILURE;
257 }
258
260 "Run number: " << MSG::dec << rodRunNumber << endmsg
261 << "Version code: 0x" << MSG::hex << int(state.m_verCode) << MSG::dec
262 << endmsg << "LUT triggered slice offset: "
263 << int(state.m_caloUserHeader.lut()) << endmsg
264 << "FADC triggered slice offset: " << int(state.m_caloUserHeader.ppFadc())
265 << endmsg << "FADC baseline lower bound: "
266 << int(state.m_caloUserHeader.ppLowerBound()));
267
268 int indata = 0;
269 uint8_t blockType = 0;
270 int subBlock = 0;
271
272 for (; payload != payloadEnd; ++payload) {
273 if (ZdcCaloUserHeader::isValid(*payload) && (subBlock == 0)) {
274
275 } else if (ZdcSubBlockHeader::isSubBlockHeader(*payload)) {
276 indata = 0;
277 CHECK(processPpmBlock_(state));
278
279 state.m_ppLuts.clear();
280 state.m_ppFadcs.clear();
281 state.m_ppBlock.clear();
282
283 blockType = (*payload >> 28) & 0xf;
284
285 if ((blockType & 0xd) == 0xc) {
286 state.m_subBlockHeader = ZdcSubBlockHeader(*payload);
288 "SubBlock version #" << int(state.m_subBlockHeader.version())
289 << " format #" << int(state.m_subBlockHeader.format())
290 << " seqNum (compVer) #" << int(state.m_subBlockHeader.seqNum())
291 << " nslice1 #" << int(state.m_subBlockHeader.nSlice1())
292 << " nslice2 #" << int(state.m_subBlockHeader.nSlice2())
293 );
294 subBlock = blockType & 0xe;
295 } else if (blockType == (subBlock | 1)) {
296 //m_subBlockStatus = ZdcSubBlockStatus(*payload);
297 subBlock = 0;
298 }
299 } else {
300 switch(state.m_subDetectorID){
301 case eformat::TDAQ_CALO_PREPROC:
302 CHECK(processPpmWord_(state, *payload, indata));
303 break;
304 case eformat::FORWARD_ZDC:
305 CHECK(processPpmWord_(state, *payload, indata));
306 break;
307 default:
308 break;
309 }
310 indata++;
311 }
312 }
313 CHECK(processPpmBlock_(state));
314 return StatusCode::SUCCESS;
315}
316
318 uint32_t word,
319 int indata) const {
320 if ( (state.m_subBlockHeader.format() == 0)
321 || (state.m_subBlockHeader.format() >= 2)
322 || (state.m_verCode >= 0x41)) {
323 state.m_ppBlock.push_back(word);
324 } else if ((state.m_verCode == 0x21) || (state.m_verCode == 0x31)) {
325 return processPpmStandardR3V1_(state, word, indata);
326 } else {
327 ATH_MSG_ERROR("Unsupported PPM version:format ("
328 << state.m_verCode << ":" << state.m_subBlockHeader.format()
329 <<") combination");
330 return StatusCode::FAILURE;
331 }
332 return StatusCode::SUCCESS;
333}
334
335
337 if (!state.m_ppBlock.empty()) {
338 if (state.m_subBlockHeader.format() == 0) {
339 StatusCode sc = processPpmNeutral_(state);
340 state.m_ppBlock.clear();
341 CHECK(sc);
342 return sc;
343 }
344
345 if (state.m_verCode == 0x31) {
346 StatusCode sc = processPpmCompressedR3V1_(state);
347 state.m_ppBlock.clear();
348 CHECK(sc);
349 return sc;
350 }
351
352 if (state.m_verCode == 0x41 || state.m_verCode == 0x42) {
353 StatusCode sc = processPpmBlockR4V1_(state);
354 state.m_ppBlock.clear();
355 CHECK(sc);
356 return sc;
357 }
358 }
359
360 if (!state.m_ppLuts.empty()) {
361 if (state.m_verCode == 0x21 || state.m_verCode == 0x31) {
362 StatusCode sc = processPpmBlockR3V1_(state);
363 state.m_ppLuts.clear();
364 state.m_ppFadcs.clear();
365 CHECK(sc);
366 return sc;
367 }
368 ATH_MSG_ERROR("Unknown PPM subheader format '"
369 << int(state.m_subBlockHeader.format())
370 << "' for rob version '"
371 << MSG::hex << int(state.m_verCode)
372 << MSG::dec << "'" );
373 return StatusCode::FAILURE;
374 }
375 return StatusCode::SUCCESS;
376}
377
379 uint8_t numLut = state.m_subBlockHeader.nSlice1();
380 uint8_t numFadc = state.m_subBlockHeader.nSlice2();
381 uint8_t totSlice = 3 * numLut + numFadc;
382
383 uint8_t channel = 0;
384 for ( int asic = 0 ; asic < 4 ; ++asic ) {
385 for ( int mcm = 0 ; mcm < 16 ; ++mcm ) {
386 // ----------------------------------------------------------------------
387 std::vector<uint32_t> rotated(totSlice);
388
389 for ( uint8_t slice = 0 ; slice < totSlice ; ++slice ) {
390 for ( uint8_t bit = 0 ; bit < 11 ; ++bit ) {
391 if ( state.m_ppBlock[slice * 11 + asic * (11 * totSlice) + bit + 1] & (1 << mcm))
392 rotated[slice] |= (1 << bit);
393 }
394 }
395
396 bool nonZeroData = false;
397 for (uint8_t slice = 0; slice < numLut; ++slice) {
398 if (rotated[slice]
399 || rotated[slice + numLut]
400 || rotated[slice + 2 * numLut + numFadc]) { // CP, JET
401 nonZeroData = true;
402 break;
403 }
404 }
405
406 std::vector<uint8_t> lcpVal;
407 std::vector<uint8_t> lcpBcidVec;
408 std::vector<uint8_t> ljeVal;
409 std::vector<uint8_t> ljeSat80Vec;
410 std::vector<int16_t> pedCor;
411 std::vector<uint8_t> pedEn;
412
413 std::vector<uint16_t> adcVal;
414 std::vector<uint8_t> adcExt;
415
416 if (nonZeroData) {
417 for (uint8_t slice = 0; slice < numLut; ++slice) {
418 lcpVal.push_back(rotated[slice] & 0xff);
419 ljeVal.push_back(rotated[slice + numLut] & 0xff);
420 pedCor.push_back(::pedCorrection(rotated[slice + 2 * numLut + numFadc] & 0x3ff));
421
422 lcpBcidVec.push_back((rotated[slice] >> 8) & 0x7);
423 ljeSat80Vec.push_back((rotated[slice + numLut] >> 8) & 0x7);
424 pedEn.push_back((rotated[slice + 2 * numLut + numFadc] >> 10) & 0x1);
425 }
426 }
427
428 for (uint8_t slice = 0; slice < numFadc; ++slice) {
429 if (rotated[slice + numLut]) { // CP, JET
430 nonZeroData = true;
431 break;
432 }
433 }
434
435 if (nonZeroData) {
436 for (uint8_t slice = 0; slice < numFadc; ++ slice) {
437 adcVal.push_back(rotated[slice + 2 * numLut] & 0x3ff);
438 adcExt.push_back((rotated[slice + 2 * numLut] >> 10 & 0x1) & 0x3ff);
439 }
440 }
441
443 state,
444 state.m_subBlockHeader.crate(),
445 state.m_subBlockHeader.module(),
446 channel,
447 lcpVal,
448 lcpBcidVec,
449 ljeVal,
450 ljeSat80Vec, adcVal,
451 adcExt,
452 pedCor,
453 pedEn));
454 // ---------------------------------------------------------------------
455 channel++;
456 }
457 }
458 return StatusCode::SUCCESS;
459}
460
462 uint8_t chan = 0;
463 BitReader br (state.m_ppBlock);
464 try{
465 while (chan < 64) {
466 uint8_t present = 1;
467 if (state.m_subBlockHeader.format() == 3) {
468 present = br.getField (1);
469 }
470
471 if (present == 1) {
472 uint8_t lutVal = 0;
473 uint8_t fmt = 6;
474 uint8_t lutSat=0;
475 uint8_t lutExt=0;
476 uint8_t lutPeak=0;
477
478 std::vector<uint16_t> adcVal = {0 , 0, 0, 0, 0};
479 std::vector<uint8_t> adcExt = {0 , 0, 0, 0, 0};
480
481 uint8_t minHeader = br.getField (4);
482 uint8_t minIndex = minHeader % 5;
483 if (minHeader < 15) { // Formats 0-5
484 if (minHeader < 10) { // Formats 0-1
485 fmt = minHeader / 5;
486 } else { // Formats 2-5
487 fmt = 2 + br.getField (2);
488 uint8_t haveLut = br.getField (1);
489 if (fmt == 2) {
490 if (haveLut == 1) {
491 lutVal = br.getField (3);
492 lutPeak = 1; // Even if LutVal==0 it seems
493 }
494 } else {
495 uint8_t haveExt = br.getField (1);
496 if (haveLut == 1) {
497 lutVal = br.getField (8);
498 lutExt = br.getField (1);
499 lutSat = br.getField (1);
500 lutPeak = br.getField (1);
501 }
502
503 if (haveExt == 1){
504 for(uint8_t i = 0; i < 5; ++i) {
505 adcExt[i] = br.getField (1);
506 }
507 } else {
508 adcExt[2] = lutExt;
509 }
510 }
511 }
512 adcVal = getPpmAdcSamplesR3_(state, br, fmt, minIndex);
513 } else {
514 uint8_t haveAdc = br.getField (1);
515 if (haveAdc == 1) {
516 uint16_t val = br.getField (10);
517 for(uint8_t i = 0; i < 5; ++i) {
518 adcVal[i] = val;
519 }
520 }
521 }
522 // Add Trigger Tower
523 //std::vector<uint8_t> luts = {lutVal};
525 state,
526 state.m_subBlockHeader.crate(),
527 state.m_subBlockHeader.module(),
528 chan,
529 std::vector<uint8_t> {lutVal},
530 std::vector<uint8_t> {uint8_t(lutExt | (lutSat << 1) | (lutPeak << 2))},
531 adcVal,
532 adcExt
533 ));
534 }
535 chan++;
536 }
537 }catch (const std::out_of_range& ex) {
538 ATH_MSG_WARNING("Excess Data in Sub-block");
540 }
541 return StatusCode::SUCCESS;
542}
543
545 State& state,
546 BitReader& br, uint8_t format, uint8_t minIndex) const {
547
548 std::vector<uint16_t> adc = {0, 0, 0, 0, 0};
549 uint8_t minAdc = 0;
550
551 for(uint8_t i = 0; i <5; ++i) {
552 uint8_t longField = 0;
553 uint8_t numBits = 0;
554 if (format > 2) {
555 longField = br.getField (1);
556 numBits = longField == 0? 4: (format * 2);
557 } else {
558 numBits = i == 0? 4: (format + 2);
559 }
560
561 if (i == 0) {
562 minAdc = br.getField (numBits);
563 if (longField == 0) {
564 minAdc += state.m_caloUserHeader.ppLowerBound();
565 }
566 } else {
567 adc[i] = minAdc + br.getField (numBits);
568 }
569 }
570
571 if (minIndex == 0) {
572 adc[0] = minAdc;
573 } else {
574 adc[0] = adc[minIndex];
575 adc[minIndex] = minAdc;
576 }
577 return adc;
578}
579
580
581
583 uint32_t word,
584 int inData) const {
585 StatusCode sc;
586 if (state.m_subBlockHeader.seqNum() == 63) { // Error block
587 ATH_MSG_DEBUG("Error PPM subblock");
588 //TODO: errorTool
589 } else {
590 const uint8_t numAdc = state.m_subBlockHeader.nSlice2();
591 const uint8_t numLut = state.m_subBlockHeader.nSlice1();
592 const uint8_t nTotal = numAdc + numLut;
593 const uint8_t wordsPerBlock = 8; // 16 towers (4 MCMs) / 2 per word
594 const uint8_t iBlk = inData / wordsPerBlock;
595 uint8_t iChan = state.m_subBlockHeader.seqNum() + 2 * (inData % wordsPerBlock);
596
597 if (iBlk < numLut) { // First all LUT values
598 for(uint8_t i = 0; i < 2; ++i) {
599 uint16_t subword = (word >> 16 * i) & 0x7ff;
600 state.m_ppLuts[iChan].push_back(subword);
601 iChan++;
602 }
603 } else if (iBlk < nTotal) { // Next all FADC values
604 for(uint8_t i = 0; i < 2; ++i) {
605 uint16_t subword = (word >> (16 * i)) & 0x7ff;
606 state.m_ppFadcs[iChan].push_back(subword);
607 iChan++;
608 }
609
610 } else{
611 ATH_MSG_WARNING("Error decoding Ppm word (run1)");
612 sc = StatusCode::FAILURE;
613 }
614
615 }
616 return sc;
617}
618
620 if (state.m_subBlockHeader.format() == 1) {
622 return StatusCode::SUCCESS;
623 } else if (state.m_subBlockHeader.format() >= 2) {
624 // TODO: convert compressed
626 return StatusCode::SUCCESS;
627 }
628 return StatusCode::FAILURE;
629}
630
632 BitReader br (state.m_ppBlock);
633
634 uint8_t numAdc = state.m_subBlockHeader.nSlice2();
635 uint8_t numLut = state.m_subBlockHeader.nSlice1();
636 int16_t pedCorBase = -20;
637
638
639 // for(size_t i = 0; i < state.m_ppBlock.size(); ++i) {
640 // std::bitset<32> x(state.m_ppBlock[i]);
641 // std::cout << i << " " << x << std::endl;
642 // }
643
644 try{
645 for(uint8_t chan = 0; chan < 64; ++chan) {
646 uint8_t present = 1;
647
648 std::vector<uint8_t> haveLut(numLut, 0);
649 std::vector<uint8_t> lcpVal(numLut, 0);
650
651 std::vector<uint8_t> lcpExt(numLut, 0);
652 std::vector<uint8_t> lcpSat(numLut, 0);
653 std::vector<uint8_t> lcpPeak(numLut, 0);
654 std::vector<uint8_t> lcpBcidVec(numLut, 0);
655
656 std::vector<uint8_t> ljeVal(numLut, 0);
657
658 std::vector<uint8_t> ljeLow(numLut, 0);
659 std::vector<uint8_t> ljeHigh(numLut, 0);
660 std::vector<uint8_t> ljeRes(numLut, 0);
661 std::vector<uint8_t> ljeSat80Vec(numLut, 0);
662
663 std::vector<uint16_t> adcVal(numAdc, 0);
664 std::vector<uint8_t> adcExt(numAdc, 0);
665 std::vector<int16_t> pedCor(numLut, 0);
666 std::vector<uint8_t> pedEn(numLut, 0);
667
668 int8_t encoding = -1;
669 int8_t minIndex = -1;
670
671 if (state.m_subBlockHeader.format() == 3) {
672 present = br.getField (1);
673 }
674 if (present == 1) {
675 interpretPpmHeaderR4V1_(br, numAdc, encoding, minIndex);
676 CHECK((encoding != -1) && (minIndex != -1));
677 // First get the LIT related quantities
678 if (encoding < 3) {
679 // Get the peal finder bits
680 for(uint i=0; i < numLut; ++i) {
681 lcpPeak[i] = br.getField (1);
682 }
683 // Get Sat80 low bits
684 if (encoding > 0) {
685 for (uint8_t i = 0; i < numLut; ++i) {
686 ljeLow[i] = br.getField (1);
687 }
688 }
689 // Get LutCP and LutJEP values (these are
690 // only present if the peak finder is set).
691 if (encoding == 2) {
692 for (uint8_t i = 0; i < numLut; ++i) {
693 if (lcpPeak[i] == 1) {
694 lcpVal[i] = br.getField (4);
695 }
696 }
697 for(uint8_t i = 0; i < numLut; ++i) {
698 if (lcpPeak[i] == 1){
699 ljeVal[i] = br.getField (3);
700 }
701 }
702 }
703 } else if (encoding < 6) {
704 // Get LUT presence flag for each LUT slice.
705 for(uint8_t i = 0; i < numLut; ++i){
706 haveLut[i] = br.getField (1);
707 }
708
709 // Get external BCID bits (if block is present).
710 uint8_t haveExt = br.getField (1);
711
712 if (haveExt == 1) {
713 for (uint8_t i = 0; i < numAdc; ++i) {
714 adcExt[i] = br.getField (1);
715 }
716 }
717
718 for(uint8_t i = 0; i < numLut; ++i){
719 if (haveLut[i] == 1) {
720 lcpVal[i] = br.getField (8);
721 lcpExt[i] = br.getField (1);
722 lcpSat[i] = br.getField (1);
723 lcpPeak[i] = br.getField (1);
724 }
725 }
726 // Get JEP LUT values and corresponding bits.
727 for(uint8_t i = 0; i < numLut; ++i){
728 if (haveLut[i] == 1) {
729 ljeVal[i] = br.getField (8);
730 ljeLow[i] = br.getField (1);
731 ljeHigh[i] = br.getField (1);
732 ljeRes[i] = br.getField (1);
733 }
734 }
735
736 }
737
738 }
739
740 if (minIndex < 0)
741 return StatusCode::FAILURE;
742
743 // Next get the ADC related quantities (all encodings).
744 adcVal = getPpmAdcSamplesR4_(state, br, encoding, minIndex);
745 // Finally get the pedestal correction.
746 if ((encoding < 3) || (encoding == 6)) {
747 for (uint8_t i = 0; i < numLut; ++i)
748 {
749 pedCor[i] = br.getField (6) + pedCorBase;
750 if (state.m_subBlockHeader.compVer() > 0) {
751 pedEn[i] = 1;
752 }
753 }
754 } else {
755 // At the moment there is an enabled bit for every LUT slice
756 // (even though its really a global flag).
757 // The correction values is a twos complement signed value.
758 for (uint8_t i = 0; i < numLut; ++i)
759 {
760 uint16_t val = br.getField (10);
761 pedCor[i] = ::pedCorrection(val);
762 pedEn[i] = br.getField (1);
763 }
764 }
765
766 for(uint8_t i=0; i < numLut; ++i){
767 lcpBcidVec[i] = uint8_t((lcpPeak[i] << 2) | (lcpSat[i] << 1) | lcpExt[i]);
768 ljeSat80Vec[i] = uint8_t((ljeRes[i] << 2) | (ljeHigh[i] << 1) | ljeLow[i]);
769 }
771 chan, lcpVal, lcpBcidVec, ljeVal, ljeSat80Vec, adcVal, adcExt, pedCor,
772 pedEn));
773 }
774 } catch (const std::out_of_range& ex) {
775 ATH_MSG_WARNING("Excess Data in Sub-block");
777 }
778 return StatusCode::SUCCESS;
779
780}
781
783 uint8_t numAdc,
784 int8_t& encoding, int8_t& minIndex) const {
785 uint8_t minHeader = 0;
786
787 if (numAdc == 5) {
788 minHeader = br.getField (4);
789 //ATH_MSG_DEBUG("SASHA: minHeader=" << int(minHeader));
790 minIndex = minHeader % 5;
791 if (minHeader < 15){ // Encodings 0-5
792 if (minHeader < 10) {
793 encoding = minHeader / 5;
794 } else {
795 encoding = 2 + br.getField (2);
796 }
797 } else {
798 encoding = 6;
799 }
800 } else {
801 uint8_t numBits = 0;
802 if (numAdc ==3 ) {
803 numBits = 2;
804 } else if (numAdc == 7) {
805 numBits = 3;
806 } else if (numAdc < 16) {
807 numBits = 4;
808 }
809
810 if (numBits > 0) {
811 uint8_t fieldSize = 1 << numBits;
812 minHeader = br.getField (numBits);
813 uint8_t encValue = fieldSize - 1;
814 if (minHeader == encValue) { // Encoding 6
815 encoding = 6;
816 minIndex = 0;
817 } else {
818 minHeader += br.getField (2) << numBits;
819 minIndex = minHeader % fieldSize;
820 encValue = 3 * fieldSize;
821
822 if (minHeader < encValue) { // Encodings 0-2
823 encoding = minHeader / fieldSize;
824 } else {
825 encoding = 3 + br.getField (2);
826 }
827 }
828 }
829 }
830}
831
833 State& state,
834 BitReader& br, uint8_t encoding, uint8_t minIndex) const {
835 uint8_t numAdc = state.m_subBlockHeader.nSlice2();
836
837 if (encoding == 6) {
838 uint16_t val = br.getField (6);
839 return std::vector<uint16_t>(numAdc, val);
840 } else if ( encoding < 3) {
841 std::vector<uint16_t> adc(numAdc, 0);
842 uint16_t minAdc = br.getField (5) + state.m_caloUserHeader.ppLowerBound();
843 adc[minIndex] = minAdc;
844 for(uint8_t i = 1; i < numAdc; ++i) {
845 adc[i == minIndex? 0: i] = br.getField (encoding + 2) + minAdc;
846 }
847 return adc;
848 } else {
849 std::vector<uint16_t> adc(numAdc, 0);
850 uint16_t minAdc = br.getField (1)
851 ? br.getField (encoding * 2)
852 : (br.getField (5) +
854
855 adc[minIndex] = minAdc;
856 for (uint8_t i = 1; i < numAdc; ++i) {
857 adc[minIndex == i? 0: i] = br.getField (
858 br.getField (1)? encoding * 2: 4
859 ) + minAdc;
860 }
861 return adc;
862 }
863}
864
866 if (state.m_subBlockHeader.format() == 1) {
868 return StatusCode::SUCCESS;
869 } else if (state.m_subBlockHeader.format() >= 2) {
870 // TODO: convert compressed
871 return StatusCode::FAILURE;
872 }
873 return StatusCode::FAILURE;
874}
875
877
878 //std::cout << "Here I am in processPpmStandardR4V1_" << std::endl;
879 uint8_t numAdc = state.m_subBlockHeader.nSlice2();
880 uint8_t numLut = state.m_subBlockHeader.nSlice1();
881 uint8_t crate = state.m_subBlockHeader.crate();
882 uint8_t module = state.m_subBlockHeader.module();
883
884
885 BitReader br (state.m_ppBlock);
886
887 for (uint8_t chan = 0; chan < 64; ++chan) {
888 //for (uint8_t k = 0; k < 4; ++k) {
889 std::vector<uint8_t> lcpVal;
890 std::vector<uint8_t> lcpBcidVec;
891
892 std::vector<uint8_t> ljeVal;
893 std::vector<uint8_t> ljeSat80Vec;
894
895
896
897 std::vector<uint16_t> adcVal;
898 std::vector<uint8_t> adcExt;
899 std::vector<int16_t> pedCor;
900 std::vector<uint8_t> pedEn;
901 try {
902 for (int i = 0; i < numLut; ++i) {
903 lcpVal.push_back(br.getField (8));
904 lcpBcidVec.push_back(br.getField (3));
905 }
906
907 for (int i = 0; i < numLut; ++i) {
908 ljeVal.push_back(br.getField (8));
909 ljeSat80Vec.push_back(br.getField (3));
910 }
911
912 for (int i = 0; i < numAdc; ++i) {
913 adcVal.push_back(br.getField (10));
914 adcExt.push_back(br.getField (1));
915 }
916
917 for (int i = 0; i < numLut; ++i) {
918 uint16_t pc = br.getField (10);
919 pedCor.push_back(pedCorrection(pc));
920 pedEn.push_back(br.getField (1));
921 }
922 } catch (const std::out_of_range& ex) {
923 ATH_MSG_WARNING("Excess Data in Sub-block");
925 }
926 CHECK(
927 addTriggerTowerV2_(state, crate, module, chan, lcpVal, lcpBcidVec,
928 ljeVal, ljeSat80Vec, adcVal, adcExt, pedCor, pedEn));
929 }
930
931 return StatusCode::SUCCESS;
932}
933
935 for(const auto& lut : state.m_ppLuts) {
937 state,
938 state.m_subBlockHeader.crate(),
939 state.m_subBlockHeader.module(),
940 lut.first,
941 lut.second,
942 state.m_ppFadcs[lut.first]));
943 }
944 return StatusCode::SUCCESS;
945}
946
948 State& state,
949 uint8_t crate,
950 uint8_t module,
951 uint8_t channel,
952 const std::vector<uint8_t>& lcpVal,
953 const std::vector<uint8_t>& lcpBcidVec,
954 const std::vector<uint8_t>& ljeVal,
955 const std::vector<uint8_t>& ljeSat80Vec,
956 const std::vector<uint16_t>& adcVal,
957 const std::vector<uint8_t>& adcExt,
958 const std::vector<int16_t>& pedCor,
959 const std::vector<uint8_t>& pedEn) const {
960
961 //int layer = 0;
962 int error = 0;
963 double eta = 0.;
964 double phi = 0.;
965
966 bool isNotSpare = false; // PAS - just to minimize changing code
967 // PAS - not using L1Calo PPMMap
968 /*
969 bool isNotSpare = m_ppmMaps->mapping(crate, module, channel, eta, phi, layer);
970 if (!isNotSpare && !m_ppmIsRetSpare && !m_ppmIsRetMuon){
971 return StatusCode::SUCCESS;
972 }
973 */
974
975 if (!isNotSpare) {
976 const int pin = channel % 16;
977 const int asic = channel / 16;
978 eta = 16 * crate + module;
979 phi = 4 * pin + asic;
980 }
981
982 uint32_t coolId = ::coolId(crate, module, channel);
983 CHECK(state.m_coolIds.count(coolId) == 0);
984 state.m_coolIds.insert(coolId);
985
987 //std::cout << ZdcToString(*tt) << std::endl;
988
989 state.m_triggerTowers->push_back(tt);
990 // tt->initialize(
991 // const uint_least32_t& coolId,
992 // const uint_least8_t& layer,
993 // const float& eta,
994 // const float& phi,
995 // const std::vector<uint_least8_t>& lut_cp,
996 // const std::vector<uint_least8_t>& lut_jep,
997 // const std::vector<int_least16_t>& correction,
998 // const std::vector<uint_least8_t>& correctionEnabled,
999 // const std::vector<uint_least8_t>& bcidVec,
1000 // const std::vector<uint_least16_t>& adc,
1001 // const std::vector<uint_least8_t>& bcidExt,
1002 // const std::vector<uint_least8_t>& sat80,
1003 // const uint_least16_t& error,
1004 // const uint_least8_t& peak,
1005 // const uint_least8_t& adcPeak
1006 // );
1007 tt->initialize(coolId, eta, phi, lcpVal, ljeVal, pedCor, pedEn,
1008 lcpBcidVec, adcVal, adcExt, ljeSat80Vec, error, state.m_caloUserHeader.lut(),
1009 state.m_caloUserHeader.ppFadc());
1010 return StatusCode::SUCCESS;
1011}
1012
1014 State& state,
1015 uint8_t crate,
1016 uint8_t module,
1017 uint8_t channel,
1018 const std::vector<uint8_t>& luts,
1019 const std::vector<uint8_t>& lcpBcidVec,
1020 const std::vector<uint16_t>& fadc,
1021 const std::vector<uint8_t>& bcidExt
1022 ) const {
1023
1024 std::vector<uint8_t> ljeSat80Vec;
1025
1026 std::vector<int16_t> pedCor;
1027 std::vector<uint8_t> pedEn;
1028
1029 CHECK(addTriggerTowerV2_(state, crate, module, channel, luts, lcpBcidVec,
1030 luts , ljeSat80Vec, fadc, bcidExt, pedCor, pedEn)
1031 );
1032
1033 return StatusCode::SUCCESS;
1034}
1035
1037 State& state,
1038 uint8_t crate,
1039 uint8_t module,
1040 uint8_t channel,
1041 const std::vector<uint16_t>& luts,
1042 const std::vector<uint16_t>& fadc
1043 ) const {
1044
1045 std::vector<uint8_t> lcpVal;
1046 std::vector<uint8_t> lcpBcidVec;
1047
1048 std::vector<uint16_t> adcVal;
1049 std::vector<uint8_t> adcExt;
1050
1051 for(auto lut: luts) {
1052 lcpVal.push_back(BitField::get<uint8_t>(lut, 0, 8));
1053 lcpBcidVec.push_back(BitField::get<uint8_t>(lut, 8, 3));
1054 }
1055
1056 for(auto f: fadc) {
1057 adcExt.push_back(BitField::get<uint8_t>(f, 0, 1));
1058 adcVal.push_back(BitField::get<uint16_t>(f, 1, 10));
1059 }
1060
1061 CHECK(addTriggerTowerV1_(state, crate, module, channel, lcpVal, lcpBcidVec,
1062 adcVal, adcExt));
1063
1064 return StatusCode::SUCCESS;
1065}
1066
1068{
1069 const int crates = 8;
1070 m_ppmSourceIDs.clear();
1071 m_ppmSourceIDsSpare.clear();
1072 m_ppmSourceIDsMuon.clear();
1073
1074 for (int crate = 0; crate < crates; ++crate) {
1075 for (int slink = 0; slink < m_srcIdMap->maxSlinks(); ++slink) {
1076 //const uint32_t rodId = m_srcIdMap->getRodID(crate, slink, 0,
1077 // eformat::TDAQ_CALO_PREPROC);
1078 const uint32_t rodId = m_srcIdMap->getRodID(crate, slink, 0,
1079 eformat::FORWARD_ZDC);
1080 const uint32_t robId = m_srcIdMap->getRobID(rodId);
1081 m_ppmSourceIDs.push_back(robId);
1082 //std::cout << "robId=" << std::hex << robId << std::dec << std::endl;
1083 if (crate > 1 && crate < 6) {
1084 m_ppmSourceIDsSpare.push_back(robId);
1085 if (crate < 4 && slink == 0) {
1086 m_ppmSourceIDsMuon.push_back(robId);
1087 }
1088 }
1089 }
1090 }
1091}
1092
1093// Return reference to vector with all possible Source Identifiers
1094
1095const std::vector<uint32_t>& ZdcByteStreamReadV1V2Tool::ppmSourceIDs(
1096 const std::string& sgKey) const
1097{
1098 if (sgKey.find("Muon") != std::string::npos) {
1099 return m_ppmSourceIDsMuon;
1100 }
1101 else if (sgKey.find("Spare") != std::string::npos) {
1102 return m_ppmSourceIDsSpare;
1103 }
1104
1105 return m_ppmSourceIDs;
1106}
1107
1108
1109
1111 (const uint8_t numBits)
1112{
1113 if ((m_ppPointer + numBits) <= m_ppMaxBit) {
1114 uint32_t iWord = m_ppPointer / 31;
1115 uint8_t iBit = m_ppPointer % 31;
1116 m_ppPointer += numBits;
1117
1118 uint32_t result;
1119 if ((iBit + numBits) <= 31) {
1120 result = ::bitFieldSize(m_ppBlock[iWord], iBit, numBits);
1121 } else {
1122 uint8_t nb1 = 31 - iBit;
1123 uint8_t nb2 = numBits - nb1;
1124 uint32_t field1 = ::bitFieldSize(m_ppBlock[iWord], iBit, nb1);
1125 uint32_t field2 = ::bitFieldSize(m_ppBlock[iWord + 1], 0, nb2);
1126 result = field1 | (field2 << nb1);
1127 }
1128
1129 return result;
1130 }
1131
1132 throw std::out_of_range("Requested too much bits from ppm block");
1133}
1134
1136{
1137 typedef std::map<uint32_t,ZdcDigits*> hashmapType;
1138 hashmapType digits_map;
1139 Identifier chan_id;
1140
1141 for (const xAOD::TriggerTower* tt : *ttCollection)
1142 {
1143 uint32_t coolId = tt->coolId();
1144 uint32_t pin = (coolId>>8) & 0xf;
1145 uint32_t asic = coolId & 0xf;
1146 uint32_t slinkChannel = asic*16 + pin;
1147 uint32_t ppmChannel = slink2ppmChannel[slinkChannel];
1148
1149 uint32_t module = (coolId>>16) & 0xf;
1150
1151 ATH_MSG_DEBUG( "--> ZCS: " << ZdcCablingService::getInstance() << " mod=" << module << " slinkC=" << slinkChannel << " ppmC=" << ppmChannel );
1152 chan_id = ZdcCablingService::getInstance()->h2s_channel_id(module, ppmChannel);
1153
1154 const uint32_t chan_hash = chan_id.get_identifier32().get_compact();
1155 int gain = ZdcCablingService::getInstance()->hwid2gain(module,ppmChannel);
1156 int delay = ZdcCablingService::getInstance()->hwid2delay(module,ppmChannel);
1157
1158 ATH_MSG_DEBUG("Trying to find chan_hash " << chan_hash << " g" << gain << "d" << delay);
1159
1160 hashmapType::iterator iter = digits_map.find(chan_hash);
1161 if (iter == digits_map.end())
1162 {
1163 ATH_MSG_DEBUG("new channel for " << chan_id);
1164 digits_map.insert(std::pair<uint32_t,ZdcDigits*>(chan_hash,new ZdcDigits(chan_id)));
1165 iter = digits_map.find(chan_hash);
1166 }
1167 if (iter != digits_map.end())
1168 {
1169 ATH_MSG_DEBUG("new auxdata for " << chan_id);
1170 if (gain==0&&delay==0) (*iter).second->set_digits_gain0_delay0( tt->adc() );
1171 if (gain==1&&delay==0) (*iter).second->set_digits_gain1_delay0( tt->adc() );
1172 if (gain==0&&delay==1) (*iter).second->set_digits_gain0_delay1( tt->adc() );
1173 if (gain==1&&delay==1) (*iter).second->set_digits_gain1_delay1( tt->adc() );
1174 }
1175
1176 }
1177
1178 ZdcDigitsCollection* zdcCollection = new ZdcDigitsCollection();
1179
1180 hashmapType::iterator iter = digits_map.begin();
1181 hashmapType::iterator iter_end = digits_map.end();
1182
1183 while (iter != iter_end)
1184 {
1185 /*
1186 Identifier id = ((*iter).second)->identify();
1187 std::cout
1188 << "side=" << m_zdcID->side(id)
1189 << " mod=" << m_zdcID->module(id)
1190 << " type=" << m_zdcID->type(id)
1191 << " chan=" << m_zdcID->channel(id)
1192 << std::endl;
1193 ((*iter).second)->print();
1194 */
1195 zdcCollection->push_back((*iter).second);
1196 ++iter;
1197 }
1198
1199 return zdcCollection;
1200}
1201
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define endmsg
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
#define CHECK(...)
Evaluate an expression and check for errors.
double delay(std::size_t d)
unsigned int uint
static Double_t sc
const char *const fmt
const int slink2ppmChannel[64]
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
const ServiceHandle< StoreGateSvc > & detStore() const
T get(const uint32_t &word) const
value_type push_back(value_type pElem)
Add an element to the end of the collection.
std::vector< const ROBF * > VROBFRAG
value_type get_compact() const
Get the compact id.
Identifier32 get_identifier32() const
Get the 32-bit version Identifier, will be invalid if >32 bits needed.
const std::vector< uint32_t > & m_ppBlock
OFFLINE_FRAGMENTS_NAMESPACE::PointerType RODPointer
ZdcDigitsCollection * convertTT2ZD(xAOD::TriggerTowerContainer *const ttCollection) const
virtual StatusCode initialize()
Dummy implementation of the initialisation function.
StatusCode processPpmStandardR4V1_(State &state) const
void interpretPpmHeaderR4V1_(BitReader &br, uint8_t numAdc, int8_t &encoding, int8_t &minIndex) const
StatusCode processPpmWord_(State &state, uint32_t word, int indata) const
std::vector< uint32_t > m_ppmSourceIDs
StatusCode addTriggerTowerV2_(State &state, uint8_t crate, uint8_t module, uint8_t channel, const std::vector< uint8_t > &lcpVal, const std::vector< uint8_t > &lcpBcidVec, const std::vector< uint8_t > &ljeVal, const std::vector< uint8_t > &ljeSat80Vec, const std::vector< uint16_t > &adcVal, const std::vector< uint8_t > &adcExt, const std::vector< int16_t > &pedCor, const std::vector< uint8_t > &pedEn) const
StatusCode processPpmBlockR3V1_(State &state) const
IROBDataProviderSvc::VROBFRAG::const_iterator ROBIterator
StatusCode processPpmCompressedR3V1_(State &state) const
StatusCode processPpmCompressedR4V1_(State &state) const
std::vector< uint32_t > m_ppmSourceIDsMuon
StatusCode convert(const IROBDataProviderSvc::VROBFRAG &robFrags, xAOD::TriggerTowerContainer *const ttCollection) const
Convert ROB fragments to trigger towers.
ZdcByteStreamReadV1V2Tool(const std::string &name)
StatusCode processPpmStandardR3V1_(State &state) const
OFFLINE_FRAGMENTS_NAMESPACE::PointerType ROBPointer
std::vector< uint16_t > getPpmAdcSamplesR4_(State &state, BitReader &br, uint8_t encoding, uint8_t minIndex) const
ServiceHandle< IROBDataProviderSvc > m_robDataProvider
Service for reading bytestream.
StatusCode processPpmBlockR4V1_(State &state) const
StatusCode addTriggerTowerV1_(State &state, uint8_t crate, uint8_t module, uint8_t channel, const std::vector< uint16_t > &luts, const std::vector< uint16_t > &fadc) const
std::vector< uint32_t > m_ppmSourceIDsSpare
StatusCode processPpmNeutral_(State &state) const
StatusCode processRobFragment_(State &state, const ROBIterator &robFrag, const RequestType &requestedType) const
StatusCode processPpmBlock_(State &state) const
const std::vector< uint32_t > & ppmSourceIDs(const std::string &sgKey) const
Return reference to vector with all possible Source Identifiers.
std::vector< uint16_t > getPpmAdcSamplesR3_(State &state, BitReader &br, uint8_t format, uint8_t minIndex) const
ToolHandle< ZdcL1CaloErrorByteStreamTool > m_errorTool
int hwid2gain(int crate, int channel) const
static const ZdcCablingService * getInstance()
get pointer to service instance
int hwid2delay(int crate, int channel) const
Identifier h2s_channel_id(int crate, int channel) const
L1Calo User Header class.
uint8_t ppFadc() const
uint8_t ppLowerBound() const
Definition ZdcID.h:25
This class provides conversion between Lower level Source ID to higher level source ID for L1Calo Byt...
Definition ZdcSrcIdMap.h:24
static int crate(uint32_t code)
moduleID -> crate
static int slink(uint32_t code)
moduleID -> slink
L1Calo User Header class.
uint8_t crate() const
uint8_t nSlice2() const
bool isSubBlockHeader() const
uint8_t compVer() const
uint8_t format() const
uint8_t version() const
uint8_t seqNum() const
uint8_t module() const
uint8_t nSlice1() const
AsgTool(const std::string &name)
Constructor specifying the tool instance's name.
Definition AsgTool.cxx:58
TriggerTowerContainer_v2 TriggerTowerContainer
Define the latest version of the TriggerTower container.
setScaleOne setStatusOne setSaturated int16_t
TriggerTower_v2 TriggerTower
Define the latest version of the TriggerTower class.
TriggerTowerAuxContainer_v2 TriggerTowerAuxContainer
Define the latest version of the TriggerTower auxiliary container.
setEventNumber uint32_t
std::map< uint8_t, std::vector< uint16_t > > m_ppFadcs
xAOD::TriggerTowerContainer * m_triggerTowers
std::map< uint8_t, std::vector< uint16_t > > m_ppLuts
MsgStream & msg
Definition testRead.cxx:32