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