1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 ////////////////////////////////////////////////////////////////////////////
18 // Decoding data from the TRD raw stream //
19 // and translation into ADC values, on-line tracklets and tracks //
21 // Author: J. Klein (jochen.klein@cern.ch) //
23 ////////////////////////////////////////////////////////////////////////////
28 #include "TClonesArray.h"
32 #include "AliRawReader.h"
33 #include "AliTRDdigitsManager.h"
34 #include "AliTRDdigitsParam.h"
35 #include "AliTRDtrapConfig.h"
36 #include "AliTRDarrayADC.h"
37 #include "AliTRDarrayDictionary.h"
38 #include "AliTRDSignalIndex.h"
39 #include "AliTRDtrackletWord.h"
40 #include "AliESDTrdTrack.h"
41 #include "AliTreeLoader.h"
42 #include "AliLoader.h"
44 #include "AliTRDrawStream.h"
47 #include "AliRunLoader.h"
49 ClassImp(AliTRDrawStream)
51 // some static information
52 Int_t AliTRDrawStream::fgMcmOrder[] = {12, 13, 14, 15,
56 Int_t AliTRDrawStream::fgRobOrder [] = {0, 1, 2, 3};
57 const Int_t AliTRDrawStream::fgkNlinks = 12;
58 const Int_t AliTRDrawStream::fgkNstacks = 5;
59 const Int_t AliTRDrawStream::fgkNsectors = 18;
60 const Int_t AliTRDrawStream::fgkNtriggers = 12;
61 const UInt_t AliTRDrawStream::fgkDataEndmarker = 0x00000000;
62 const UInt_t AliTRDrawStream::fgkTrackletEndmarker = 0x10001000;
64 const char* AliTRDrawStream::fgkErrorMessages[] = {
66 "Link monitor active",
67 "Pretrigger counter mismatch",
68 "not a TRD equipment (1024-1041)",
69 "Invalid Stack header",
70 "Invalid detector number",
71 "No digits could be retrieved from the digitsmanager",
73 "HC check bits wrong",
74 "Unexpected position in readout stream",
75 "Invalid testpattern mode",
76 "Testpattern mismatch",
77 "Number of timebins changed",
78 "ADC mask inconsistent",
79 "ADC check bits invalid",
81 "Missing expected ADC channels",
85 Int_t AliTRDrawStream::fgErrorDebugLevel[] = {
106 AliTRDrawStream::ErrorBehav_t AliTRDrawStream::fgErrorBehav[] = {
107 AliTRDrawStream::kTolerate,
108 AliTRDrawStream::kDiscardHC,
109 AliTRDrawStream::kTolerate,
110 AliTRDrawStream::kAbort,
111 AliTRDrawStream::kAbort,
112 AliTRDrawStream::kAbort,
113 AliTRDrawStream::kAbort,
114 AliTRDrawStream::kDiscardHC,
115 AliTRDrawStream::kDiscardHC,
116 AliTRDrawStream::kTolerate,
117 AliTRDrawStream::kTolerate,
118 AliTRDrawStream::kTolerate,
119 AliTRDrawStream::kTolerate,
120 AliTRDrawStream::kTolerate,
121 AliTRDrawStream::kTolerate,
122 AliTRDrawStream::kTolerate,
123 AliTRDrawStream::kTolerate,
124 AliTRDrawStream::kTolerate
127 AliTRDrawStream::AliTRDrawStream(AliRawReader *rawReader) :
129 fStoreError(&AliTRDrawStream::ForgetError),
130 fRawReader(rawReader),
146 fCurrSmHeaderSize(0),
147 fCurrSmHeaderVersion(0),
148 fCurrTrailerReadout(0),
149 fCurrTrgHeaderAvail(0),
150 fCurrTrgHeaderReadout(0),
151 fCurrTrkHeaderAvail(0),
153 fCurrTriggerEnable(0),
154 fCurrTriggerFired(0),
156 fCurrTrackletEnable(0),
158 fCurrTrkHeaderIndexWord(0x0),
159 fCurrTrkHeaderSize(0x0),
160 fCurrTrgHeaderIndexWord(0x0),
161 fCurrTrgHeaderSize(0x0),
162 fCurrStackIndexWord(0x0),
163 fCurrStackHeaderSize(0x0),
164 fCurrStackHeaderVersion(0x0),
166 fCurrCleanCheckout(0x0),
170 fCurrLinkMonitorFlags(0x0),
171 fCurrLinkDataTypeFlags(0x0),
172 fCurrLinkDebugFlags(0x0),
196 // default constructor
198 fCurrTrkHeaderIndexWord = new UInt_t[fgkNstacks];
199 fCurrTrkHeaderSize = new UInt_t[fgkNstacks];
200 fCurrTrgHeaderIndexWord = new UInt_t[fgkNtriggers];
201 fCurrTrgHeaderSize = new UInt_t[fgkNtriggers];
202 fCurrStackIndexWord = new UInt_t[fgkNstacks];
203 fCurrStackHeaderSize = new UInt_t[fgkNstacks];
204 fCurrStackHeaderVersion = new UInt_t[fgkNstacks];
205 fCurrLinkMask = new UInt_t[fgkNstacks];
206 fCurrCleanCheckout = new UInt_t[fgkNstacks];
207 fCurrBoardId = new UInt_t[fgkNstacks];
208 fCurrHwRevTMU = new UInt_t[fgkNstacks];
209 fCurrLinkMonitorFlags = new UInt_t[fgkNstacks * fgkNlinks];
210 fCurrLinkDataTypeFlags = new UInt_t[fgkNstacks * fgkNlinks];
211 fCurrLinkDebugFlags = new UInt_t[fgkNstacks * fgkNlinks];
212 for (Int_t i = 0; i < 100; i++)
215 // preparing TClonesArray
216 fTrackletArray = new TClonesArray("AliTRDtrackletWord", 256);
218 // setting up the error tree
219 fErrors = new TTree("errorStats", "Error statistics");
220 fErrors->SetDirectory(0x0);
221 fErrors->Branch("error", &fLastError);
222 fErrors->SetCircular(1000);
223 for (Int_t i = 0; i < 100; i++) {
229 AliTRDrawStream::~AliTRDrawStream()
235 delete [] fCurrTrkHeaderIndexWord;
236 delete [] fCurrTrkHeaderSize;
237 delete [] fCurrTrgHeaderIndexWord;
238 delete [] fCurrTrgHeaderSize;
239 delete [] fCurrStackIndexWord;
240 delete [] fCurrStackHeaderSize;
241 delete [] fCurrStackHeaderVersion;
242 delete [] fCurrLinkMask;
243 delete [] fCurrCleanCheckout;
244 delete [] fCurrBoardId;
245 delete [] fCurrHwRevTMU;
246 delete [] fCurrLinkMonitorFlags;
247 delete [] fCurrLinkDataTypeFlags;
248 delete [] fCurrLinkDebugFlags;
251 Bool_t AliTRDrawStream::ReadEvent(TTree *trackletTree)
253 // read the current event from the raw reader and fill it to the digits manager
256 AliError("No raw reader available");
261 ConnectTracklets(trackletTree);
266 // loop over all DDLs
267 // data starts with GTU payload, i.e. SM index word
268 UChar_t *buffer = 0x0;
270 while (fRawReader->ReadNextData(buffer)) {
272 fCurrEquipmentId = fRawReader->GetEquipmentId();
273 AliDebug(2, Form("equipment: %i", fCurrEquipmentId));
275 if (fCurrEquipmentId < kDDLOffset || fCurrEquipmentId > kDDLMax) {
276 EquipmentError(kNonTrdEq, "Skipping");
281 new ((*fMarkers)[fMarkers->GetEntriesFast()])
282 AliTRDrawStreamError(-kSecactive, fCurrEquipmentId - kDDLOffset);
284 ReadGTUHeaders((UInt_t*) buffer);
286 if (fCurrTrailerReadout)
289 // loop over all active links
290 AliDebug(2, Form("Stack mask 0x%02x", fCurrStackMask));
291 for (Int_t iStack = 0; iStack < fgkNstacks; iStack++) {
293 if ((fCurrStackMask & (1 << fCurrSlot)) == 0)
296 AliDebug(2, Form("Stack %i, Link mask: 0x%02x", fCurrSlot, fCurrLinkMask[fCurrSlot]));
297 for (Int_t iLink = 0; iLink < fgkNlinks; iLink++) {
299 fCurrHC = (fCurrEquipmentId - kDDLOffset) * fgkNstacks * fgkNlinks +
300 fCurrSlot * fgkNlinks + iLink;
301 if ((fCurrLinkMask[fCurrSlot] & (1 << fCurrLink)) == 0)
305 // check for link monitor error flag
306 if (fCurrLinkMonitorFlags[fCurrSlot*fgkNlinks + fCurrLink] != 0)
307 LinkError(kLinkMonitor);
309 // read the data from one HC
312 // read all data endmarkers
322 Bool_t AliTRDrawStream::NextDDL()
324 // continue reading with the next equipment
329 fCurrEquipmentId = 0;
333 UChar_t *buffer = 0x0;
335 while (fRawReader->ReadNextData(buffer)) {
337 fCurrEquipmentId = fRawReader->GetEquipmentId();
338 AliDebug(2, Form("equipment: %i", fCurrEquipmentId));
340 if (fCurrEquipmentId < kDDLOffset || fCurrEquipmentId > kDDLMax) {
341 EquipmentError(kNonTrdEq, "Skipping");
346 new ((*fMarkers)[fMarkers->GetEntriesFast()])
347 AliTRDrawStreamError(-kSecactive, fCurrEquipmentId - kDDLOffset);
349 ReadGTUHeaders((UInt_t*) buffer);
351 if (fCurrTrailerReadout)
361 Int_t AliTRDrawStream::NextChamber(AliTRDdigitsManager *digMgr)
363 // read the data for the next chamber
364 // in case you only want to read the data of a single chamber
365 // to read all data ReadEvent(...) is recommended
367 fDigitsManager = digMgr;
372 // tracklet output preparation
373 TTree *trklTree = 0x0;
374 AliRunLoader *rl = AliRunLoader::Instance();
375 AliLoader* trdLoader = rl ? rl->GetLoader("TRDLoader") : NULL;
376 AliDataLoader *trklLoader = trdLoader ? trdLoader->GetDataLoader("tracklets") : NULL;
378 AliTreeLoader *trklTreeLoader = (AliTreeLoader*) trklLoader->GetBaseLoader("tracklets-raw");
380 trklTree = trklTreeLoader->Tree();
382 trklTree = trklLoader->Tree();
385 if (fTrackletTree != trklTree)
386 ConnectTracklets(trklTree);
389 AliError("No raw reader available");
393 while (fCurrSlot < 0 || fCurrSlot >= fgkNstacks) {
398 while ((fCurrSlot < fgkNstacks) &&
399 (((fCurrStackMask & (1 << fCurrSlot)) == 0) ||
400 ((fCurrLinkMask[fCurrSlot] & (1 << fCurrLink))) == 0)) {
402 if (fCurrLink >= fgkNlinks) {
409 AliDebug(2, Form("Stack %i, Link %i, mask: 0x%02x", fCurrSlot, fCurrLink, fCurrLinkMask[fCurrSlot]));
410 fCurrHC = (fCurrEquipmentId - kDDLOffset) * fgkNlinks * fgkNstacks +
411 fCurrSlot * fgkNlinks + fCurrLink;
413 if (fCurrLinkMonitorFlags[fCurrSlot*fgkNlinks + fCurrLink] != 0)
414 LinkError(kLinkMonitor);
416 // read the data from one HC
419 // read all data endmarkers
422 if (fCurrLink % 2 == 0) {
423 // if we just read the A-side HC then also check the B-side
426 if (fCurrLinkMask[fCurrSlot] & (1 << fCurrLink)) {
435 if (fCurrLink >= fgkNlinks) {
439 } while ((fCurrSlot < fgkNstacks) &&
440 (((fCurrStackMask & (1 << fCurrSlot)) == 0) ||
441 ((fCurrLinkMask[fCurrSlot] & (1 << fCurrLink))) == 0));
443 // return chamber information from HC if it is valid
444 // otherwise return information from link position
445 if (fCurrSm < 0 || fCurrSm >= fgkNsectors || fCurrStack < 0 || fCurrStack >= fgkNstacks || fCurrLayer < 0 || fCurrLayer >= fgkNlinks/2)
446 return ((fCurrEquipmentId-kDDLOffset) + fCurrSlot * fgkNlinks/2 + fCurrLink/2);
448 return (fCurrSm * fgkNstacks*fgkNlinks/2 + fCurrStack * fgkNlinks/2 + fCurrLayer);
452 Int_t AliTRDrawStream::ReadGTUHeaders(UInt_t *buffer)
454 // check the data source and read the headers
456 if (fCurrEquipmentId >= kDDLOffset && fCurrEquipmentId <= kDDLMax) {
459 // setting the pointer to data and current reading position
460 fPayloadCurr = fPayloadStart = buffer;
461 fPayloadSize = fRawReader->GetDataSize() / sizeof(UInt_t);
462 fStats.fStatsSector[fCurrEquipmentId - kDDLOffset].fBytes = fRawReader->GetDataSize();
463 AliDebug(2, Form("Read buffer of size: %i", fRawReader->GetDataSize()));
465 AliDebug(1, DumpRaw("raw data", fPayloadCurr, TMath::Min(fPayloadSize, 1000)));
468 if (ReadSmHeader() < 0) {
469 AliError(Form("Reading SM header failed, skipping this DDL %i", fCurrEquipmentId));
473 // read tracking headers (if available)
474 if (fCurrTrkHeaderAvail) {
475 for (Int_t iStack = 0; iStack < fgkNstacks; iStack++) {
476 if ((fCurrStackMask & (1 << iStack)) != 0)
477 ReadTrackingHeader(iStack);
481 // read trigger header(s) (if available)
482 if (fCurrTrgHeaderAvail)
483 ReadTriggerHeaders();
486 for (Int_t iStack = 0; iStack < fgkNstacks; iStack++) {
487 if ((fCurrStackMask & (1 << iStack)) != 0)
488 ReadStackHeader(iStack);
497 Int_t AliTRDrawStream::ReadSmHeader()
499 // read the SMU index header at the current reading position
500 // and store the information in the corresponding variables
502 if (fPayloadCurr - fPayloadStart >= fPayloadSize - 1) {
503 EquipmentError(kUnknown, "SM Header incomplete");
507 fCurrSmHeaderSize = ((*fPayloadCurr) >> 16) & 0xffff;
508 fCurrSmHeaderVersion = ((*fPayloadCurr) >> 12) & 0xf;
509 fCurrTrackEnable = ((*fPayloadCurr) >> 6) & 0x1;
510 fCurrTrackletEnable = ((*fPayloadCurr) >> 5) & 0x1;
511 fCurrStackMask = ((*fPayloadCurr) ) & 0x1f;
512 fCurrHwRev = (fPayloadCurr[1] >> 12) & 0xffff;
514 switch (fCurrSmHeaderVersion) {
516 fCurrTrailerReadout = 0;
517 fCurrTrgHeaderAvail = 0;
519 fCurrTrkHeaderAvail = 0;
525 fCurrTrailerReadout = ((*fPayloadCurr) >> 10) & 0x1;
526 fCurrTrgHeaderAvail = 1;
527 fCurrTrgHeaderReadout = ((*fPayloadCurr) >> 9) & 0x1;
528 fCurrEvType = ((*fPayloadCurr) >> 7) & 0x3;
529 fCurrTrkHeaderAvail = fCurrTrackEnable;
530 fCurrTriggerEnable = (fPayloadCurr[2] >> 8) & 0xfff;
531 fCurrTriggerFired = (fPayloadCurr[2] >> 20) & 0xfff;
535 AliError(Form("unknown SM header version: 0x%x", fCurrSmHeaderVersion));
538 AliDebug(5, Form("SM header: size: %i, version: %i, track enable: %i, tracklet enable: %i, stack mask: %2x, trailer: %i, trgheader: %i, trkheader: %i",
540 fCurrSmHeaderVersion,
546 fCurrTrkHeaderAvail ));
548 // jump to the first word after the SM header
549 fPayloadCurr += fCurrSmHeaderSize + 1;
551 return fCurrSmHeaderSize + 1;
554 Int_t AliTRDrawStream::DecodeGTUtracks()
556 // decode GTU track words
557 // this depends on the hardware revision of the SMU
559 Int_t sector = fCurrEquipmentId-kDDLOffset;
561 if ((sector < 0) || (sector > 17)) {
562 AliError(Form("Invalid sector %i for GTU tracks", sector));
566 AliDebug(1, DumpRaw(Form("GTU tracks in sector %2i (hw rev %i)", sector, fCurrHwRev),
567 fPayloadCurr + 4, 10, 0xffe0ffff));
569 if (fCurrHwRev < 1772) {
570 UInt_t fastWord; // fast trigger word
571 ULong64_t trackWord = 0; // extended track word
574 for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
575 if (fPayloadCurr[iWord] == 0x10000000) { // stack boundary marker
581 ((fPayloadCurr[iWord] & 0xfffff0f0) == 0x13370000)) {
582 fastWord = fPayloadCurr[iWord];
583 AliDebug(1, Form("stack %i: fast trigger word: 0x%08x", stack, fastWord));
586 else if ((idx & 0x1) == 0x1) {
587 trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
588 AliDebug(1,Form("track debug word: 0x%016llx", trackWord));
590 AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
593 trk->SetSector(sector);
594 trk->SetStack((trackWord >> 60) & 0x7);
598 trk->SetLayerMask((trackWord >> 16) & 0x3f);
599 trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
600 trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
601 trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
602 trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
603 trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
604 trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
609 Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
610 if (TMath::Abs(pt) > 0.1) {
611 trk->SetA((Int_t) (0.15*51625./100./pt / 160e-4 * 2));
616 trackWord = fPayloadCurr[iWord];
622 else if (fCurrHwRev < 1804) {
623 UInt_t fastWord; // fast trigger word
624 ULong64_t trackWord = 0; // extended track word
627 for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
628 if (fPayloadCurr[iWord] == 0xffe0ffff) { // stack boundary marker
634 ((fPayloadCurr[iWord] & 0xfffff0f0) == 0x13370000)) {
635 fastWord = fPayloadCurr[iWord];
636 AliDebug(1, Form("stack %i: fast trigger word: 0x%08x", stack, fastWord));
639 else if ((idx & 0x1) == 0x1) {
640 trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
641 AliDebug(1, Form("track debug word: 0x%016llx", trackWord));
643 AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
646 trk->SetSector(fCurrEquipmentId-kDDLOffset);
647 trk->SetStack((trackWord >> 60) & 0x7);
651 trk->SetLayerMask((trackWord >> 16) & 0x3f);
652 trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
653 trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
654 trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
655 trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
656 trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
657 trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
662 Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
663 if (TMath::Abs(pt) > 0.1) {
664 trk->SetA((Int_t) (0.15*51625./100./pt / 160e-4 * 2));
669 trackWord = fPayloadCurr[iWord];
675 else if (fCurrHwRev < 1819) {
676 UInt_t fastWord; // fast trigger word
677 ULong64_t trackWord = 0; // extended track word
680 for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
681 if (fPayloadCurr[iWord] == 0xffe0ffff) { // stack boundary marker
687 ((fPayloadCurr[iWord] & 0xfffff0f0) == 0x13370000)) {
688 fastWord = fPayloadCurr[iWord];
689 AliDebug(1, Form("stack %i: fast trigger word: 0x%08x", stack, fastWord));
692 else if ((idx & 0x1) == 0x1) {
693 trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
694 AliDebug(1, Form("track debug word: 0x%016llx", trackWord));
697 AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
700 trk->SetSector(fCurrEquipmentId-kDDLOffset);
701 trk->SetStack((trackWord >> 60) & 0x7);
704 // trk->SetPt(((trackWord & 0xffff) ^ 0x8000) - 0x8000);
706 trk->SetLayerMask((trackWord >> 16) & 0x3f);
707 trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
708 trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
709 trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
710 trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
711 trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
712 trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
717 Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
718 if (TMath::Abs(pt) > 0.1) {
719 trk->SetA((Int_t) (0.15*51625./100./trk->Pt() / 160e-4 * 2));
724 trackWord = fPayloadCurr[iWord];
730 else if (fCurrHwRev < 1860) {
731 UInt_t fastWord; // fast trigger word
732 ULong64_t trackWord = 0; // extended track word
735 Bool_t upperWord = kFALSE;
737 for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
738 if (fPayloadCurr[iWord] == 0xffe0ffff) { // stack boundary marker
744 // assemble the 32-bit words out of 16-bit blocks
746 word |= (fPayloadCurr[iWord] & 0xffff0000);
750 // lower word is read first
751 word = (fPayloadCurr[iWord] & 0xffff0000) >> 16;
756 if ((word & 0xffff0008) == 0x13370008) {
758 AliDebug(1, Form("stack %i: fast track word: 0x%08x", stack, fastWord));
761 else if ((idx & 0x1) == 0x1) {
762 trackWord |= ((ULong64_t) word) << 32;
763 AliDebug(1, Form("track debug word: 0x%016llx", trackWord));
765 AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
768 trk->SetSector(fCurrEquipmentId-kDDLOffset);
769 trk->SetStack((trackWord >> 60) & 0x7);
773 trk->SetLayerMask((trackWord >> 16) & 0x3f);
774 trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
775 trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
776 trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
777 trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
778 trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
779 trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
784 Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
785 if (TMath::Abs(pt) > 0.1) {
786 trk->SetA((Int_t) (0.15*51625./100./pt / 160e-4 * 2));
799 ULong64_t trackWord = 0; // this is the debug word
802 Bool_t upperWord = kFALSE;
804 for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
805 if (fPayloadCurr[iWord] == 0xffe0ffff) {
811 // assemble the 32-bit words out of 16-bit blocks
813 word |= (fPayloadCurr[iWord] & 0xffff0000);
817 // lower word is read first
818 word = (fPayloadCurr[iWord] & 0xffff0000) >> 16;
823 if ((word & 0xffff0008) == 0x13370008) {
824 AliDebug(1, Form("stack %i: fast track word: 0x%08x", stack, word));
827 else if ((word & 0xffff0010) == 0x13370010) {
828 AliDebug(1, Form("stack %i: tracking done word: 0x%08x", stack, word));
831 else if ((idx & 0x1) == 0x1) {
832 trackWord |= ((ULong64_t) word) << 32;
833 AliDebug(1, Form("track debug word: 0x%16llx", trackWord));
835 AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
837 trk->SetSector(fCurrEquipmentId-kDDLOffset);
838 trk->SetStack((trackWord >> 60) & 0x7);
842 trk->SetLayerMask((trackWord >> 16) & 0x3f);
843 trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
844 trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
845 trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
846 trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
847 trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
848 trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
853 Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
854 if (TMath::Abs(pt) > 0.1) {
855 trk->SetA(-(Int_t) (0.15*51625./100./pt / 160e-4 * 2));
869 Int_t AliTRDrawStream::ReadTrackingHeader(Int_t stack)
871 // read the tracking information and store it for the given stack
875 fCurrTrkHeaderIndexWord[stack] = *fPayloadCurr;
876 fCurrTrkHeaderSize[stack] = ((*fPayloadCurr) >> 16) & 0x3ff;
878 AliDebug(1, Form("tracking header index word: 0x%08x, size: %i (hw rev: %i)",
879 fCurrTrkHeaderIndexWord[stack], fCurrTrkHeaderSize[stack], fCurrHwRev));
880 Int_t trackingTime = *fPayloadCurr & 0x3ff;
885 ULong64_t trackWord = 0;
887 Int_t trackIndex = fTracks ? fTracks->GetEntriesFast() : -1;
889 for (UInt_t iWord = 0; iWord < fCurrTrkHeaderSize[stack]; iWord++) {
892 // first part of 64-bit word
893 trackWord = fPayloadCurr[iWord];
896 trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
898 if (trackWord & (1ul << 63)) {
899 if ((trackWord & (0x3ful << 56)) != 0) {
901 AliDebug(2, Form("track word: 0x%016llx", trackWord));
904 AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
907 trk->SetSector(fCurrEquipmentId-kDDLOffset);
908 trk->SetLayerMask((trackWord >> 56) & 0x3f);
909 trk->SetA( (((trackWord >> 38) & 0x3ffff) ^ 0x20000) - 0x20000);
910 trk->SetB( (((trackWord >> 20) & 0x3ffff) ^ 0x20000) - 0x20000);
911 trk->SetC( (((trackWord >> 8) & 0xffff) ^ 0x8000) - 0x8000);
912 trk->SetPID((trackWord >> 0) & 0xff);
913 trk->SetStack(stack);
915 // now compare the track word with the one generated from the ESD information
916 if (trackWord != trk->GetTrackWord(0)) {
917 AliError(Form("track word 0x%016llx does not match the read one 0x%016llx",
918 trk->GetTrackWord(0), trackWord));
923 // done marker (so far only used to set trigger flag)
925 AliDebug(2, Form("seg / stack / first / last / done / index : %i %i %lli %lli %lli %i",
926 fCurrEquipmentId - kDDLOffset, stack,
927 (trackWord >> 20) & 0x3ff,
928 (trackWord >> 10) & 0x3ff,
929 (trackWord >> 0) & 0x3ff,
934 // extended track word
935 AliDebug(2, Form("extended track word: 0x%016llx", trackWord));
938 AliESDTrdTrack *trk = (AliESDTrdTrack*) (*fTracks)[trackIndex];
940 trk->SetFlags((trackWord >> 52) & 0x7ff);
941 trk->SetReserved((trackWord >> 49) & 0x7);
942 trk->SetY((trackWord >> 36) & 0x1fff);
943 trk->SetTrackletIndex((trackWord >> 0) & 0x3f, 0);
944 trk->SetTrackletIndex((trackWord >> 6) & 0x3f, 1);
945 trk->SetTrackletIndex((trackWord >> 12) & 0x3f, 2);
946 trk->SetTrackletIndex((trackWord >> 18) & 0x3f, 3);
947 trk->SetTrackletIndex((trackWord >> 24) & 0x3f, 4);
948 trk->SetTrackletIndex((trackWord >> 30) & 0x3f, 5);
950 if (trackWord != trk->GetExtendedTrackWord(0)) {
951 AliError(Form("extended track word 0x%016llx does not match the read one 0x%016llx",
952 trk->GetExtendedTrackWord(0), trackWord));
962 fPayloadCurr += fCurrTrkHeaderSize[stack];
964 return fCurrTrkHeaderSize[stack];
967 Int_t AliTRDrawStream::ReadTriggerHeaders()
969 // read all trigger headers present
971 AliDebug(1, Form("trigger mask: 0x%03x, fired: 0x%03x\n",
972 fCurrTriggerEnable, fCurrTriggerFired));
973 // loop over potential trigger blocks
974 for (Int_t iTrigger = 0; iTrigger < fgkNtriggers; iTrigger++) {
975 // check for trigger enable
976 if (fCurrTriggerEnable & (1 << iTrigger)) {
977 // check for readout mode and trigger fired
978 if ((fCurrTrgHeaderReadout == 0) || (fCurrTriggerFired & (1 << iTrigger))) {
980 AliDebug(1, Form("trigger index word %i: 0x%08x\n", iTrigger, *fPayloadCurr));
981 fCurrTrgHeaderIndexWord[iTrigger] = *fPayloadCurr;
982 fCurrTrgHeaderSize[iTrigger] = ((*fPayloadCurr) >> 16) & 0x3ff;
985 fPayloadCurr += fCurrTrgHeaderSize[iTrigger];
993 Int_t AliTRDrawStream::ReadStackHeader(Int_t stack)
995 // read the stack header
996 // and store the information in the corresponding variables
998 fCurrStackIndexWord[stack] = *fPayloadCurr;
999 fCurrStackHeaderSize[stack] = (((*fPayloadCurr) >> 16) & 0xffff) + 1;
1000 fCurrStackHeaderVersion[stack] = ((*fPayloadCurr) >> 12) & 0xf;
1001 fCurrLinkMask[stack] = (*fPayloadCurr) & 0xfff;
1003 // dumping stack header
1004 AliDebug(1, DumpRaw(Form("stack %i header", stack), fPayloadCurr, fCurrStackHeaderSize[stack]));
1006 if (fPayloadCurr - fPayloadStart >= fPayloadSize - (Int_t) fCurrStackHeaderSize[stack]) {
1007 LinkError(kStackHeaderInvalid, "Stack index header aborted");
1011 switch (fCurrStackHeaderVersion[stack]) {
1013 if (fCurrStackHeaderSize[stack] < 8) {
1014 LinkError(kStackHeaderInvalid, "Stack header smaller than expected!");
1018 fCurrCleanCheckout[stack] = fPayloadCurr[1] & 0x1;
1019 fCurrBoardId[stack] = (fPayloadCurr[1] >> 8) & 0xff;
1020 fCurrHwRevTMU[stack] = (fPayloadCurr[1] >> 16) & 0xffff;
1022 for (Int_t iLayer = 0; iLayer < 6; iLayer++) {
1024 fCurrLinkMonitorFlags [stack*fgkNlinks + iLayer*2] = fPayloadCurr[iLayer+2] & 0xf;
1025 fCurrLinkDataTypeFlags [stack*fgkNlinks + iLayer*2] = (fPayloadCurr[iLayer+2] >> 4) & 0x3;
1026 fCurrLinkDebugFlags [stack*fgkNlinks + iLayer*2] = (fPayloadCurr[iLayer+2] >> 12) & 0xf;
1028 fCurrLinkMonitorFlags [stack*fgkNlinks + iLayer*2 + 1] = (fPayloadCurr[iLayer+2] >> 16) & 0xf;
1029 fCurrLinkDataTypeFlags [stack*fgkNlinks + iLayer*2 + 1] = (fPayloadCurr[iLayer+2] >> 20) & 0x3;
1030 fCurrLinkDebugFlags [stack*fgkNlinks + iLayer*2 + 1] = (fPayloadCurr[iLayer+2] >> 28) & 0xf;
1035 LinkError(kStackHeaderInvalid, "Invalid Stack Header version %x", fCurrStackHeaderVersion[stack]);
1038 fPayloadCurr += fCurrStackHeaderSize[stack];
1040 return fCurrStackHeaderSize[stack];
1043 Int_t AliTRDrawStream::ReadGTUTrailer()
1045 // read the SM trailer containing CRCs from various stages
1047 UInt_t* trailer = fPayloadStart + fPayloadSize -1;
1049 // look for the trailer index word from the end
1050 for (Int_t iWord = 0; iWord < fPayloadSize; iWord++) {
1051 if ((fPayloadStart[fPayloadSize-1-iWord] & 0xffff) == 0x1f51) {
1052 trailer = fPayloadStart + fPayloadSize - 1 - iWord;
1057 if (((*trailer) & 0xffff) == 0x1f51) {
1058 UInt_t trailerIndexWord = (*trailer);
1059 Int_t trailerSize = (trailerIndexWord >> 16) & 0xffff;
1060 AliDebug(2, DumpRaw("GTU trailer", trailer, trailerSize+1));
1061 // parse the trailer
1064 EquipmentError(kUnknown, "trailer index marker mismatch");
1069 Int_t AliTRDrawStream::ReadLinkData()
1071 // read the data in one link (one HC) until the data endmarker is reached
1072 // returns the number of words read!
1075 UInt_t* startPosLink = fPayloadCurr;
1077 AliDebug(1, DumpRaw(Form("link data from seg %2i slot %i link %2i", fCurrEquipmentId-kDDLOffset, fCurrSlot, fCurrLink),
1078 fPayloadCurr, TMath::Min((Int_t) (fPayloadSize - (fPayloadCurr-fPayloadStart)), 100), 0x00000000));
1081 new ((*fMarkers)[fMarkers->GetEntriesFast()])
1082 AliTRDrawStreamError(-kHCactive, fCurrEquipmentId-kDDLOffset, fCurrStack, fCurrLink);
1084 if (fErrorFlags & kDiscardHC)
1087 //??? add check whether tracklets are enabled
1088 count += ReadTracklets();
1089 if (fErrorFlags & kDiscardHC)
1092 AliDebug(1, DumpRaw("HC header", fPayloadCurr, 4, 0x00000000));
1093 count += ReadHcHeader();
1094 if (fErrorFlags & kDiscardHC)
1097 Int_t det = fCurrSm * 30 + fCurrStack * 6 + fCurrLayer;
1099 if (det > -1 && det < 540) {
1101 if ((fAdcArray = fDigitsManager->GetDigits(det))) {
1102 //fAdcArray->Expand();
1103 if (fAdcArray->GetNtime() != fCurrNtimebins)
1104 fAdcArray->Allocate(16, 144, fCurrNtimebins);
1107 LinkError(kNoDigits);
1110 if (!fDigitsParam) {
1111 fDigitsParam = fDigitsManager->GetDigitsParam();
1114 fDigitsParam->SetPretriggerPhase(det, fCurrPtrgPhase);
1115 fDigitsParam->SetNTimeBins(det, fCurrNtimebins);
1116 fDigitsParam->SetADCbaseline(det, 10);
1119 if (fDigitsManager->UsesDictionaries()) {
1120 fDigitsManager->GetDictionary(det, 0)->Reset();
1121 fDigitsManager->GetDictionary(det, 1)->Reset();
1122 fDigitsManager->GetDictionary(det, 2)->Reset();
1125 if ((fSignalIndex = fDigitsManager->GetIndexes(det))) {
1126 fSignalIndex->SetSM(fCurrSm);
1127 fSignalIndex->SetStack(fCurrStack);
1128 fSignalIndex->SetLayer(fCurrLayer);
1129 fSignalIndex->SetDetNumber(det);
1130 if (!fSignalIndex->IsAllocated())
1131 fSignalIndex->Allocate(16, 144, fCurrNtimebins);
1134 // ----- check which kind of data -----
1135 if (fCurrMajor & 0x40) {
1136 if ((fCurrMajor & 0x7) == 0x7) {
1137 AliDebug(1, "This is a config event");
1138 UInt_t *startPos = fPayloadCurr;
1139 while (fPayloadCurr - fPayloadStart < fPayloadSize &&
1140 *fPayloadCurr != fgkDataEndmarker)
1142 count += fPayloadCurr - startPos;
1144 // feeding TRAP config
1145 AliTRDtrapConfig *trapcfg = AliTRDtrapConfig::Instance();
1146 trapcfg->ReadPackedConfig(fCurrHC, startPos, fPayloadCurr - startPos);
1149 Int_t tpmode = fCurrMajor & 0x7;
1150 AliDebug(1, Form("Checking testpattern (mode %i) data", tpmode));
1154 else if (fCurrMajor & 0x20) {
1155 AliDebug(1, "This is a zs event");
1156 count += ReadZSData();
1159 AliDebug(1, "This is a nozs event");
1160 count += ReadNonZSData();
1164 LinkError(kInvalidDetector, "%i", det);
1165 while (fPayloadCurr - fPayloadStart < fPayloadSize &&
1166 *fPayloadCurr != fgkDataEndmarker)
1170 if (fCurrSm > -1 && fCurrSm < 18) {
1171 fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fBytes += (fPayloadCurr - startPosLink) * sizeof(UInt_t);
1172 fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fBytesRead += count * sizeof(UInt_t);
1173 fStats.fStatsSector[fCurrSm].fBytesRead += count * sizeof(UInt_t);
1174 fStats.fBytesRead += count * sizeof(UInt_t);
1180 Int_t AliTRDrawStream::ReadTracklets()
1182 // read the tracklets from one HC
1184 fTrackletArray->Clear();
1186 UInt_t *start = fPayloadCurr;
1187 while (*(fPayloadCurr) != fgkTrackletEndmarker &&
1188 fPayloadCurr - fPayloadStart < fPayloadSize) {
1189 new ((*fTrackletArray)[fTrackletArray->GetEntriesFast()]) AliTRDtrackletWord(*(fPayloadCurr), fCurrHC);
1194 if (fTrackletArray->GetEntriesFast() > 0) {
1195 AliDebug(1, Form("Found %i tracklets in %i %i %i (ev. %i)", fTrackletArray->GetEntriesFast(),
1196 (fCurrEquipmentId-kDDLOffset), fCurrSlot, fCurrLink, fRawReader->GetEventIndex()));
1197 if (fCurrSm > -1 && fCurrSm < 18) {
1198 fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNTracklets += fTrackletArray->GetEntriesFast();
1199 fStats.fStatsSector[fCurrSm].fNTracklets += fTrackletArray->GetEntriesFast();
1202 fTrackletTree->Fill();
1204 for (Int_t iTracklet = 0; iTracklet < fTrackletArray->GetEntriesFast(); iTracklet++) {
1205 new ((*fTracklets)[fTracklets->GetEntriesFast()]) AliTRDtrackletWord(*((AliTRDtrackletWord*)(*fTrackletArray)[iTracklet]));
1209 // loop over remaining tracklet endmarkers
1210 while ((*(fPayloadCurr) == fgkTrackletEndmarker &&
1211 fPayloadCurr - fPayloadStart < fPayloadSize))
1214 return fPayloadCurr - start;
1217 Int_t AliTRDrawStream::ReadHcHeader()
1219 // read and parse the HC header of one HC
1220 // and store the information in the corresponding variables
1222 AliDebug(1, Form("HC header: 0x%08x", *fPayloadCurr));
1223 UInt_t *start = fPayloadCurr;
1224 // check not to be at the data endmarker
1225 if (*fPayloadCurr == fgkDataEndmarker)
1228 fCurrSpecial = (*fPayloadCurr >> 31) & 0x1;
1229 fCurrMajor = (*fPayloadCurr >> 24) & 0x7f;
1230 fCurrMinor = (*fPayloadCurr >> 17) & 0x7f;
1231 fCurrAddHcWords = (*fPayloadCurr >> 14) & 0x7;
1232 fCurrSm = (*fPayloadCurr >> 9) & 0x1f;
1233 fCurrLayer = (*fPayloadCurr >> 6) & 0x7;
1234 fCurrStack = (*fPayloadCurr >> 3) & 0x7;
1235 fCurrSide = (*fPayloadCurr >> 2) & 0x1;
1236 fCurrCheck = (*fPayloadCurr) & 0x3;
1238 if ((fCurrSm != (((Int_t) fCurrEquipmentId) - kDDLOffset)) ||
1239 (fCurrStack != fCurrSlot) ||
1240 (fCurrLayer != fCurrLink / 2) ||
1241 (fCurrSide != fCurrLink % 2)) {
1242 LinkError(kHCmismatch,
1243 "HC: %i, %i, %i, %i\n 0x%08x 0x%08x 0x%08x 0x%08x",
1244 fCurrSm, fCurrStack, fCurrLayer, fCurrSide,
1245 fPayloadCurr[0], fPayloadCurr[1], fPayloadCurr[2], fPayloadCurr[3]);
1247 if (fCurrCheck != 0x1) {
1248 LinkError(kHCcheckFailed);
1251 if (fCurrAddHcWords > 0) {
1252 fCurrNtimebins = (fPayloadCurr[1] >> 26) & 0x3f;
1253 fCurrBC = (fPayloadCurr[1] >> 10) & 0xffff;
1254 fCurrPtrgCnt = (fPayloadCurr[1] >> 6) & 0xf;
1255 fCurrPtrgPhase = (fPayloadCurr[1] >> 2) & 0xf;
1258 fPayloadCurr += 1 + fCurrAddHcWords;
1260 return (fPayloadCurr - start);
1263 Int_t AliTRDrawStream::ReadTPData(Int_t mode)
1265 // testing of testpattern 1 to 3 (hardcoded), 0 missing
1266 // evcnt checking missing
1268 Int_t cpufromchannel[] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3};
1271 Int_t mcmcount = -1;
1272 Int_t wordcount = 0;
1273 Int_t channelcount = 0;
1275 UInt_t expadcval = 0;
1277 Int_t lastmcmpos = -1;
1278 Int_t lastrobpos = -1;
1280 UInt_t* start = fPayloadCurr;
1282 while (*(fPayloadCurr) != fgkDataEndmarker &&
1283 fPayloadCurr - fPayloadStart < fPayloadSize - 1) {
1285 // ----- Checking MCM Header -----
1286 AliDebug(2, Form("MCM header: 0x%08x", *fPayloadCurr));
1289 // ----- checking for proper readout order - ROB -----
1290 if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
1291 lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
1294 ROBError(kPosUnexp, Form("#%i after #%i in readout order", GetROBReadoutPos(ROB(*fPayloadCurr) / 2), lastrobpos));
1296 fCurrRobPos = ROB(*fPayloadCurr);
1298 // ----- checking for proper readout order - MCM -----
1299 if (GetMCMReadoutPos(MCM(*fPayloadCurr)) >= (lastmcmpos + 1) % 16) {
1300 lastmcmpos = GetMCMReadoutPos(MCM(*fPayloadCurr));
1303 MCMError(kPosUnexp, Form("#%i after #%i in readout order", GetMCMReadoutPos(MCM(*fPayloadCurr)), lastmcmpos));
1305 fCurrMcmPos = MCM(*fPayloadCurr);
1310 evcnt = 0x3f & *fPayloadCurr >> 26;
1313 while (channelcount < 21) {
1315 if (cpu != cpufromchannel[channelcount]) {
1316 cpu = cpufromchannel[channelcount];
1317 expadcval = (1 << 9) | (fCurrRobPos << 6) | (fCurrMcmPos << 2) | cpu;
1321 while (count < 10) {
1322 if (channelcount % 2 == 0)
1329 expword |= expadcval << 2;
1330 expadcval = ( (expadcval << 1) | ( ( (expadcval >> 9) ^ (expadcval >> 6) ) & 1) ) & 0x3FF;
1331 expword |= expadcval << 12;
1332 expadcval = ( (expadcval << 1) | ( ( (expadcval >> 9) ^ (expadcval >> 6) ) & 1) ) & 0x3FF;
1333 expword |= expadcval << 22;
1334 expadcval = ( (expadcval << 1) | ( ( (expadcval >> 9) ^ (expadcval >> 6) ) & 1) ) & 0x3FF;
1336 else if (mode == 2) {
1337 // ----- TP 2 ------
1338 expword = ((0x3f & evcnt) << 26) | ((fCurrSm + 1) << 21) | ((fCurrLayer + 1) << 18) |
1339 ((fCurrStack + 1) << 15) |
1340 (fCurrRobPos << 12) | (fCurrMcmPos << 8) | (cpu << 6) | (wordcount + 1);
1342 else if (mode == 3) {
1344 expword = ((0xfff & evcnt) << 20) | (fCurrSm << 15) | (fCurrLink/2 << 12) | (fCurrStack << 9) |
1345 (fCurrRobPos << 6) | (fCurrMcmPos << 2) | (cpu << 0);
1349 LinkError(kTPmodeInvalid, "Just reading");
1352 diff = *fPayloadCurr ^ expword;
1354 MCMError(kTPmismatch,
1355 "Seen 0x%08x, expected 0x%08x, diff: 0x%08x (0x%02x)",
1356 *fPayloadCurr, expword, diff, 0xff & (diff | diff >> 8 | diff >> 16 | diff >> 24));;
1364 // continue with next MCM
1366 return fPayloadCurr - start;
1370 Int_t AliTRDrawStream::ReadZSData()
1372 // read the zs data from one link from the current reading position
1374 UInt_t *start = fPayloadCurr;
1377 Int_t mcmcountExp = fCurrStack == 2 ? 48 : 64;
1378 Int_t channelcount = 0;
1379 Int_t channelcountExp = 0;
1380 Int_t channelcountMax = 0;
1382 Int_t currentTimebin = 0;
1385 Int_t lastmcmpos = -1;
1386 Int_t lastrobpos = -1;
1388 if (fCurrNtimebins != fNtimebins) {
1390 LinkError(kNtimebinsChanged,
1391 "No. of timebins changed from %i to %i", fNtimebins, fCurrNtimebins);
1392 fNtimebins = fCurrNtimebins;
1395 timebins = fNtimebins;
1397 while (*(fPayloadCurr) != fgkDataEndmarker &&
1398 fPayloadCurr - fPayloadStart < fPayloadSize) {
1400 // ----- Checking MCM Header -----
1401 AliDebug(2, DumpMcmHeader("MCM header: ", *fPayloadCurr));
1402 UInt_t *startPosMCM = fPayloadCurr;
1404 // ----- checking for proper readout order - ROB -----
1405 if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
1406 if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) > lastrobpos)
1408 lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
1411 ROBError(kPosUnexp, Form("#%i after #%i and #%i in readout order",
1412 GetROBReadoutPos(ROB(*fPayloadCurr) / 2), lastrobpos, GetROBReadoutPos(fCurrRobPos)));
1414 fCurrRobPos = ROB(*fPayloadCurr);
1416 // ----- checking for proper readout order - MCM -----
1417 if (GetMCMReadoutPos(MCM(*fPayloadCurr)) > lastmcmpos) {
1418 lastmcmpos = GetMCMReadoutPos(MCM(*fPayloadCurr));
1421 MCMError(kPosUnexp, Form("#%i after #%i and #%i in readout order",
1422 GetMCMReadoutPos(MCM(*fPayloadCurr)), lastmcmpos, GetMCMReadoutPos(fCurrMcmPos)));
1424 fCurrMcmPos = MCM(*fPayloadCurr);
1426 if (EvNo(*fPayloadCurr) != evno) {
1428 evno = EvNo(*fPayloadCurr);
1430 MCMError(kPtrgCntMismatch, "%i <-> %i", evno, EvNo(*fPayloadCurr));
1433 Int_t adccoloff = AdcColOffset(*fPayloadCurr);
1434 Int_t padcoloff = PadColOffset(*fPayloadCurr);
1435 Int_t row = Row(*fPayloadCurr);
1438 // ----- Reading ADC channels -----
1439 AliDebug(2, DumpAdcMask("ADC mask: ", *fPayloadCurr));
1441 // ----- analysing the ADC mask -----
1443 channelcountExp = GetNActiveChannelsFromMask(*fPayloadCurr);
1444 channelcountMax = GetNActiveChannels(*fPayloadCurr);
1445 Int_t channelmask = GetActiveChannels(*fPayloadCurr);
1446 Int_t channelno = -1;
1449 if (channelcountExp != channelcountMax) {
1450 if (channelcountExp > channelcountMax) {
1451 Int_t temp = channelcountExp;
1452 channelcountExp = channelcountMax;
1453 channelcountMax = temp;
1455 while (channelcountExp < channelcountMax && channelcountExp < 21 &&
1456 fPayloadCurr - fPayloadStart < fPayloadSize - 10 * channelcountExp - 1) {
1457 MCMError(kAdcMaskInconsistent,
1458 "Possible MCM-H: 0x%08x, possible ADC-mask: 0x%08x",
1459 *(fPayloadCurr + 10 * channelcountExp),
1460 *(fPayloadCurr + 10 * channelcountExp + 1) );
1461 if (!CouldBeMCMhdr( *(fPayloadCurr + 10 * channelcountExp)) && !CouldBeADCmask( *(fPayloadCurr + 10 * channelcountExp + 1)))
1467 MCMError(kAdcMaskInconsistent,
1468 "Inconsistency in no. of active channels: Counter: %i, Mask: %i, chosen: %i!",
1469 GetNActiveChannels(fPayloadCurr[-1]), GetNActiveChannelsFromMask(fPayloadCurr[-1]), channelcountExp);
1471 AliDebug(2, Form("expecting %i active channels, %i timebins", channelcountExp, fCurrNtimebins));
1473 // ----- reading marked ADC channels -----
1474 while (channelcount < channelcountExp && *(fPayloadCurr) != fgkDataEndmarker) {
1477 while (channelno < 20 && (channelmask & 1 << channelno) == 0)
1480 if (fCurrNtimebins > 30) {
1481 currentTimebin = ((*fPayloadCurr >> 2) & 0x3f);
1482 timebins = ((*fPayloadCurr >> 8) & 0xf) * 3;
1489 Int_t nADCwords = (timebins + 2) / 3;
1490 AliDebug(3, Form("Now reading %i words for channel %2i", nADCwords, channelno));
1491 Int_t adccol = adccoloff - channelno;
1492 Int_t padcol = padcoloff - channelno;
1493 // if (adccol < 3 || adccol > 165)
1494 // AliInfo(Form("writing channel %i of det %3i %i:%2i to adcrow/-col: %i/%i padcol: %i",
1495 // channelno, fCurrHC/2, fCurrRobPos, fCurrMcmPos, row, adccol, padcol));
1497 while ((adcwc < nADCwords) &&
1498 (*(fPayloadCurr) != fgkDataEndmarker) &&
1499 (fPayloadCurr - fPayloadStart < fPayloadSize)) {
1500 int check = 0x3 & *fPayloadCurr;
1501 if (channelno % 2 != 0) { // odd channel
1502 if (check != 0x2 && channelno < 21) {
1503 MCMError(kAdcCheckInvalid,
1504 "%i for %2i. ADC word in odd channel %i",
1505 check, adcwc+1, channelno);
1508 else { // even channel
1509 if (check != 0x3 && channelno < 21) {
1510 MCMError(kAdcCheckInvalid,
1511 "%i for %2i. ADC word in even channel %i",
1512 check, adcwc+1, channelno);
1516 // filling the actual timebin data
1517 int tb2 = 0x3ff & *fPayloadCurr >> 22;
1518 int tb1 = 0x3ff & *fPayloadCurr >> 12;
1519 int tb0 = 0x3ff & *fPayloadCurr >> 2;
1520 if (adcwc != 0 || fCurrNtimebins <= 30)
1521 fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb0);
1524 fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb1);
1525 fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb2);
1531 if (adcwc != nADCwords)
1532 MCMError(kAdcDataAbort);
1535 if (padcol > 0 && padcol < 144) {
1536 fSignalIndex->AddIndexRC(row, padcol);
1542 if (fCurrSm > -1 && fCurrSm < 18) {
1543 fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNChannels += channelcount;
1544 fStats.fStatsSector[fCurrSm].fNChannels += channelcount;
1546 if (channelcount != channelcountExp)
1547 MCMError(kAdcChannelsMiss);
1550 if (fCurrSm > -1 && fCurrSm < 18) {
1551 fStats.fStatsSector[fCurrSm].fStatsHC[fCurrHC%60].fNMCMs++;
1552 fStats.fStatsSector[fCurrSm].fNMCMs++;
1555 if (IsDumping() && DumpingMCM(fCurrHC/2, fCurrRobPos, fCurrMcmPos)) {
1556 AliInfo(DumpRaw(Form("Event %i: Det %3i ROB %i MCM %2i", fRawReader->GetEventIndex(), fCurrHC/2, fCurrRobPos, fCurrMcmPos),
1557 startPosMCM, fPayloadCurr - startPosMCM));
1560 // continue with next MCM
1563 // check for missing MCMs (if header suppression is inactive)
1564 if (((fCurrMajor & 0x1) == 0) && (mcmcount != mcmcountExp)) {
1565 LinkError(kMissMcmHeaders,
1566 "No. of MCM headers %i not as expected: %i",
1567 mcmcount, mcmcountExp);
1570 return (fPayloadCurr - start);
1573 Int_t AliTRDrawStream::ReadNonZSData()
1575 // read the non-zs data from one link from the current reading position
1577 UInt_t *start = fPayloadCurr;
1580 Int_t mcmcountExp = fCurrStack == 2 ? 48 : 64;
1581 Int_t channelcount = 0;
1582 Int_t channelcountExp = 0;
1584 Int_t currentTimebin = 0;
1587 Int_t lastmcmpos = -1;
1588 Int_t lastrobpos = -1;
1590 if (fCurrNtimebins != fNtimebins) {
1592 LinkError(kNtimebinsChanged,
1593 "No. of timebins changed from %i to %i", fNtimebins, fCurrNtimebins);
1594 fNtimebins = fCurrNtimebins;
1597 timebins = fNtimebins;
1599 while (*(fPayloadCurr) != fgkDataEndmarker &&
1600 fPayloadCurr - fPayloadStart < fPayloadSize - 2) {
1602 // ----- Checking MCM Header -----
1603 AliDebug(2, Form("MCM header: 0x%08x", *fPayloadCurr));
1605 // ----- checking for proper readout order - ROB -----
1606 if (GetROBReadoutPos(ROB(*fPayloadCurr) / 2) >= lastrobpos) {
1607 lastrobpos = GetROBReadoutPos(ROB(*fPayloadCurr) / 2);
1610 ROBError(kPosUnexp, Form("#%i after #%i in readout order", GetROBReadoutPos(ROB(*fPayloadCurr) / 2), lastrobpos));
1612 fCurrRobPos = ROB(*fPayloadCurr);
1614 // ----- checking for proper readout order - MCM -----
1615 if (GetMCMReadoutPos(MCM(*fPayloadCurr)) >= (lastmcmpos + 1) % 16) {
1616 lastmcmpos = GetMCMReadoutPos(MCM(*fPayloadCurr));
1619 MCMError(kPosUnexp, Form("#%i after #%i in readout order", GetMCMReadoutPos(MCM(*fPayloadCurr)), lastmcmpos));
1621 fCurrMcmPos = MCM(*fPayloadCurr);
1623 if (EvNo(*fPayloadCurr) != evno) {
1625 evno = EvNo(*fPayloadCurr);
1627 MCMError(kPtrgCntMismatch, "%i <-> %i", evno, EvNo(*fPayloadCurr));
1632 channelcountExp = 21;
1635 Int_t adccoloff = AdcColOffset(*fPayloadCurr);
1636 Int_t padcoloff = PadColOffset(*fPayloadCurr);
1637 Int_t row = Row(*fPayloadCurr);
1641 // ----- reading marked ADC channels -----
1642 while (channelcount < channelcountExp &&
1643 *(fPayloadCurr) != fgkDataEndmarker) {
1650 Int_t nADCwords = (timebins + 2) / 3;
1651 AliDebug(2, Form("Now looking %i words", nADCwords));
1652 Int_t adccol = adccoloff - channelno;
1653 Int_t padcol = padcoloff - channelno;
1654 while ((adcwc < nADCwords) &&
1655 (*(fPayloadCurr) != fgkDataEndmarker) &&
1656 (fPayloadCurr - fPayloadStart < fPayloadSize)) {
1657 int check = 0x3 & *fPayloadCurr;
1658 if (channelno % 2 != 0) { // odd channel
1659 if (check != 0x2 && channelno < 21) {
1660 MCMError(kAdcCheckInvalid,
1661 "%i for %2i. ADC word in odd channel %i",
1662 check, adcwc+1, channelno);
1665 else { // even channel
1666 if (check != 0x3 && channelno < 21) {
1667 MCMError(kAdcCheckInvalid,
1668 "%i for %2i. ADC word in even channel %i",
1669 check, adcwc+1, channelno);
1673 // filling the actual timebin data
1674 int tb2 = 0x3ff & *fPayloadCurr >> 22;
1675 int tb1 = 0x3ff & *fPayloadCurr >> 12;
1676 int tb0 = 0x3ff & *fPayloadCurr >> 2;
1677 if (adcwc != 0 || fCurrNtimebins <= 30)
1678 fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb0);
1681 fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb1);
1682 fAdcArray->SetDataByAdcCol(row, adccol, currentTimebin++, tb2);
1688 if (adcwc != nADCwords)
1689 MCMError(kAdcDataAbort);
1692 if (padcol > 0 && padcol < 144) {
1693 fSignalIndex->AddIndexRC(row, padcol);
1699 if (channelcount != channelcountExp)
1700 MCMError(kAdcChannelsMiss);
1702 // continue with next MCM
1705 // check for missing MCMs (if header suppression is inactive)
1706 if (mcmcount != mcmcountExp) {
1707 LinkError(kMissMcmHeaders,
1708 "%i not as expected: %i", mcmcount, mcmcountExp);
1711 return (fPayloadCurr - start);
1714 Int_t AliTRDrawStream::SeekNextLink()
1716 // proceed in raw data stream till the next link
1718 UInt_t *start = fPayloadCurr;
1720 // read until data endmarkers
1721 while (fPayloadCurr - fPayloadStart < fPayloadSize &&
1722 *fPayloadCurr != fgkDataEndmarker)
1725 // read all data endmarkers
1726 while (fPayloadCurr - fPayloadStart < fPayloadSize &&
1727 *fPayloadCurr == fgkDataEndmarker)
1730 return (fPayloadCurr - start);
1733 Bool_t AliTRDrawStream::ConnectTracklets(TTree *trklTree)
1735 // connect the tracklet tree used to store the tracklet output
1737 fTrackletTree = trklTree;
1741 if (!fTrackletTree->GetBranch("hc"))
1742 fTrackletTree->Branch("hc", &fCurrHC, "hc/I");
1744 fTrackletTree->SetBranchAddress("hc", &fCurrHC);
1746 if (!fTrackletTree->GetBranch("trkl"))
1747 fTrackletTree->Branch("trkl", &fTrackletArray);
1749 fTrackletTree->SetBranchAddress("trkl", &fTrackletArray);
1755 void AliTRDrawStream::EquipmentError(ErrorCode_t err, const char *const msg, ...)
1757 // register error according to error code on equipment level
1758 // and return the corresponding error message
1760 fLastError.fSector = fCurrEquipmentId - kDDLOffset;
1761 fLastError.fStack = -1;
1762 fLastError.fLink = -1;
1763 fLastError.fRob = -1;
1764 fLastError.fMcm = -1;
1765 fLastError.fError = err;
1766 (this->*fStoreError)();
1769 if (fgErrorDebugLevel[err] > 10)
1770 AliDebug(fgErrorDebugLevel[err],
1771 Form("Event %6i: Eq. %2d - %s : %s",
1772 fRawReader->GetEventIndex(), fCurrEquipmentId, fgkErrorMessages[err],
1773 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1775 AliError(Form("Event %6i: Eq. %2d - %s : %s",
1776 fRawReader->GetEventIndex(), fCurrEquipmentId, fgkErrorMessages[err],
1777 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1778 fErrorFlags |= fgErrorBehav[err];
1782 void AliTRDrawStream::StackError(ErrorCode_t err, const char *const msg, ...)
1784 // register error according to error code on stack level
1785 // and return the corresponding error message
1787 fLastError.fSector = fCurrEquipmentId - kDDLOffset;
1788 fLastError.fStack = fCurrSlot;
1789 fLastError.fLink = -1;
1790 fLastError.fRob = -1;
1791 fLastError.fMcm = -1;
1792 fLastError.fError = err;
1793 (this->*fStoreError)();
1796 if (fgErrorDebugLevel[err] > 0)
1797 AliDebug(fgErrorDebugLevel[err],
1798 Form("Event %6i: Eq. %2d S %i - %s : %s",
1799 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fgkErrorMessages[err],
1800 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1802 AliError(Form("Event %6i: Eq. %2d S %i - %s : %s",
1803 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fgkErrorMessages[err],
1804 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1805 fErrorFlags |= fgErrorBehav[err];
1809 void AliTRDrawStream::LinkError(ErrorCode_t err, const char *const msg, ...)
1811 // register error according to error code on link level
1812 // and return the corresponding error message
1814 fLastError.fSector = fCurrEquipmentId - kDDLOffset;
1815 fLastError.fStack = fCurrSlot;
1816 fLastError.fLink = fCurrLink;
1817 fLastError.fRob = -1;
1818 fLastError.fMcm = -1;
1819 fLastError.fError = err;
1820 (this->*fStoreError)();
1823 if (fgErrorDebugLevel[err] > 0)
1824 AliDebug(fgErrorDebugLevel[err],
1825 Form("Event %6i: Eq. %2d S %i l %2i - %s : %s",
1826 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fgkErrorMessages[err],
1827 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1829 AliError(Form("Event %6i: Eq. %2d S %i l %2i - %s : %s",
1830 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fgkErrorMessages[err],
1831 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1832 fErrorFlags |= fgErrorBehav[err];
1836 void AliTRDrawStream::ROBError(ErrorCode_t err, const char *const msg, ...)
1838 // register error according to error code on ROB level
1839 // and return the corresponding error message
1841 fLastError.fSector = fCurrEquipmentId - kDDLOffset;
1842 fLastError.fStack = fCurrSlot;
1843 fLastError.fLink = fCurrLink;
1844 fLastError.fRob = fCurrRobPos;
1845 fLastError.fMcm = -1;
1846 fLastError.fError = err;
1847 (this->*fStoreError)();
1850 if (fgErrorDebugLevel[err] > 0)
1851 AliDebug(fgErrorDebugLevel[err],
1852 Form("Event %6i: Eq. %2d S %i l %2i ROB %i - %s : %s",
1853 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fgkErrorMessages[err],
1854 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1856 AliError(Form("Event %6i: Eq. %2d S %i l %2i ROB %i - %s : %s",
1857 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fgkErrorMessages[err],
1858 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1859 fErrorFlags |= fgErrorBehav[err];
1863 void AliTRDrawStream::MCMError(ErrorCode_t err, const char *const msg, ...)
1865 // register error according to error code on MCM level
1866 // and return the corresponding error message
1868 fLastError.fSector = fCurrEquipmentId - kDDLOffset;
1869 fLastError.fStack = fCurrSlot;
1870 fLastError.fLink = fCurrLink;
1871 fLastError.fRob = fCurrRobPos;
1872 fLastError.fMcm = fCurrMcmPos;
1873 fLastError.fError = err;
1874 (this->*fStoreError)();
1877 if (fgErrorDebugLevel[err] > 0)
1878 AliDebug(fgErrorDebugLevel[err],
1879 Form("Event %6i: Eq. %2d S %i l %2i ROB %i MCM %2i - %s : %s",
1880 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fCurrMcmPos, fgkErrorMessages[err],
1881 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1883 AliError(Form("Event %6i: Eq. %2d S %i l %2i ROB %i MCM %2i - %s : %s",
1884 fRawReader->GetEventIndex(), fCurrEquipmentId, fCurrSlot, fCurrLink, fCurrRobPos, fCurrMcmPos, fgkErrorMessages[err],
1885 (va_start(ap, msg), vsprintf(fErrorBuffer, msg, ap), va_end(ap), fErrorBuffer) ));
1886 fErrorFlags |= fgErrorBehav[err];
1889 const char* AliTRDrawStream::GetErrorMessage(ErrorCode_t errCode)
1891 // return the error message for the given error code
1893 if (errCode > 0 && errCode < kLastErrorCode)
1894 return fgkErrorMessages[errCode];
1899 void AliTRDrawStream::AliTRDrawStats::ClearStats()
1901 // clear statistics (includes clearing sector-wise statistics)
1904 for (Int_t iSector = 0; iSector < 18; iSector++) {
1905 fStatsSector[iSector].ClearStats();
1910 void AliTRDrawStream::AliTRDrawStats::AliTRDrawStatsSector::ClearStats()
1912 // clear statistics (includes clearing HC-wise statistics)
1920 for (Int_t iHC = 0; iHC < 60; iHC++) {
1921 fStatsHC[iHC].ClearStats();
1925 void AliTRDrawStream::AliTRDrawStats::AliTRDrawStatsSector::AliTRDrawStatsHC::ClearStats()
1936 void AliTRDrawStream::SetDumpMCM(Int_t det, Int_t rob, Int_t mcm, Bool_t dump)
1938 // mark MCM for dumping of raw data
1941 fDumpMCM[fNDumpMCMs++] = (det << 7) | (rob << 4) | mcm;
1945 for (iMCM = 0; iMCM < fNDumpMCMs; iMCM++) {
1946 if (fDumpMCM[iMCM] == ((det << 7) | (rob << 4) | mcm)) {
1951 for ( ; iMCM < fNDumpMCMs; iMCM++) {
1952 fDumpMCM[iMCM] = fDumpMCM[iMCM+1];
1957 Bool_t AliTRDrawStream::DumpingMCM(Int_t det, Int_t rob, Int_t mcm) const
1959 // check if MCM data should be dumped
1961 for (Int_t iMCM = 0; iMCM < fNDumpMCMs; iMCM++) {
1962 if (fDumpMCM[iMCM] == ((det << 7) | (rob << 4) | mcm)) {
1969 TString AliTRDrawStream::DumpRaw(TString title, UInt_t *start, Int_t length, UInt_t endmarker)
1974 for (Int_t pos = 0; pos < length; pos += 4) {
1975 if ((start[pos+0] != endmarker) && pos+0 < length)
1976 if ((start[pos+1] != endmarker && pos+1 < length))
1977 if ((start[pos+2] != endmarker && pos+2 < length))
1978 if ((start[pos+3] != endmarker && pos+3 < length))
1979 title += Form(" 0x%08x 0x%08x 0x%08x 0x%08x\n",
1980 start[pos+0], start[pos+1], start[pos+2], start[pos+3]);
1982 title += Form(" 0x%08x 0x%08x 0x%08x 0x%08x\n",
1983 start[pos+0], start[pos+1], start[pos+2], start[pos+3]);
1987 title += Form(" 0x%08x 0x%08x 0x%08x\n",
1988 start[pos+0], start[pos+1], start[pos+2]);
1992 title += Form(" 0x%08x 0x%08x\n",
1993 start[pos+0], start[pos+1]);
1997 title += Form(" 0x%08x\n",
2005 TString AliTRDrawStream::DumpMcmHeader(TString title, UInt_t word)
2007 title += Form("0x%08x -> ROB: %i, MCM: %2i",
2008 word, ROB(word), MCM(word));
2012 TString AliTRDrawStream::DumpAdcMask(TString title, UInt_t word)
2014 title += Form("0x%08x -> #ch : %2i, 0x%06x (%2i ch)",
2015 word, GetNActiveChannels(word), GetActiveChannels(word), GetNActiveChannelsFromMask(word));
2019 AliTRDrawStream::AliTRDrawStreamError::AliTRDrawStreamError(Int_t error, Int_t sector, Int_t stack, Int_t link, Int_t rob, Int_t mcm) :