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 **************************************************************************/
18 ///////////////////////////////////////////////////////////////////////////////
20 /// This class provides access to Altro digits in raw data.
22 /// It loops over all Altro digits in the raw data given by the AliRawReader.
23 /// The Next method goes to the next digit. If there are no digits left
24 /// it returns kFALSE.
25 /// Several getters provide information about the current digit.
27 ///////////////////////////////////////////////////////////////////////////////
29 #include "AliAltroRawStream.h"
30 #include "AliRawReader.h"
33 ClassImp(AliAltroRawStream)
36 //_____________________________________________________________________________
37 AliAltroRawStream::AliAltroRawStream(AliRawReader* rawReader) :
38 fNoAltroMapping(kTRUE),
39 fIsShortDataHeader(kFALSE),
50 fRawReader(rawReader),
55 fRCUTrailerData(NULL),
65 // create an object to read Altro raw digits
66 fSegmentation[0] = fSegmentation[1] = fSegmentation[2] = -1;
69 //_____________________________________________________________________________
70 AliAltroRawStream::AliAltroRawStream(const AliAltroRawStream& stream) :
72 fNoAltroMapping(stream.fNoAltroMapping),
73 fIsShortDataHeader(stream.fIsShortDataHeader),
74 fDDLNumber(stream.fDDLNumber),
75 fPrevDDLNumber(stream.fPrevDDLNumber),
76 fRCUId(stream.fRCUId),
77 fPrevRCUId(stream.fPrevRCUId),
78 fHWAddress(stream.fHWAddress),
79 fPrevHWAddress(stream.fPrevHWAddress),
81 fPrevTime(stream.fPrevTime),
82 fSignal(stream.fSignal),
83 fTimeBunch(stream.fTimeBunch),
84 fRawReader(stream.fRawReader),
86 fPosition(stream.fPosition),
87 fCount(stream.fCount),
88 fBunchLength(stream.fBunchLength),
89 fRCUTrailerData(stream.fRCUTrailerData),
90 fRCUTrailerSize(stream.fRCUTrailerSize),
91 fFECERRA(stream.fFECERRA),
92 fFECERRB(stream.fFECERRB),
93 fERRREG2(stream.fERRREG2),
94 fActiveFECsA(stream.fActiveFECsA),
95 fActiveFECsB(stream.fActiveFECsB),
96 fAltroCFG1(stream.fAltroCFG1),
97 fAltroCFG2(stream.fAltroCFG2)
99 fSegmentation[0] = stream.fSegmentation[0];
100 fSegmentation[1] = stream.fSegmentation[1];
101 fSegmentation[2] = stream.fSegmentation[2];
104 //_____________________________________________________________________________
105 AliAltroRawStream& AliAltroRawStream::operator = (const AliAltroRawStream& stream)
107 if(&stream == this) return *this;
109 fNoAltroMapping = stream.fNoAltroMapping;
110 fIsShortDataHeader = stream.fIsShortDataHeader;
111 fDDLNumber = stream.fDDLNumber;
112 fPrevDDLNumber = stream.fPrevDDLNumber;
113 fRCUId = stream.fRCUId;
114 fPrevRCUId = stream.fPrevRCUId;
115 fHWAddress = stream.fHWAddress;
116 fPrevHWAddress = stream.fPrevHWAddress;
117 fTime = stream.fTime;
118 fPrevTime = stream.fPrevTime;
119 fSignal = stream.fSignal;
120 fTimeBunch = stream.fTimeBunch;
121 fRawReader = stream.fRawReader;
122 fData = stream.fData;
123 fPosition = stream.fPosition;
124 fCount = stream.fCount;
125 fBunchLength = stream.fBunchLength;
126 fRCUTrailerData = stream.fRCUTrailerData;
127 fRCUTrailerSize = stream.fRCUTrailerSize;
128 fFECERRA = stream.fFECERRA;
129 fFECERRB = stream.fFECERRB;
130 fERRREG2 = stream.fERRREG2;
131 fActiveFECsA = stream.fActiveFECsA;
132 fActiveFECsB = stream.fActiveFECsB;
133 fAltroCFG1 = stream.fAltroCFG1;
134 fAltroCFG2 = stream.fAltroCFG2;
136 fSegmentation[0] = stream.fSegmentation[0];
137 fSegmentation[1] = stream.fSegmentation[1];
138 fSegmentation[2] = stream.fSegmentation[2];
143 //_____________________________________________________________________________
144 AliAltroRawStream::~AliAltroRawStream()
150 //_____________________________________________________________________________
151 void AliAltroRawStream::Reset()
153 // reset altro raw stream params
155 fPosition = fCount = fBunchLength = 0;
157 fRCUTrailerData = NULL;
160 fFECERRA = fFECERRB = fERRREG2 = fActiveFECsA = fActiveFECsB = fAltroCFG1 = fAltroCFG2 = 0;
162 fDDLNumber = fPrevDDLNumber = fRCUId = fPrevRCUId = fHWAddress = fPrevHWAddress = fTime = fPrevTime = fSignal = fTimeBunch = -1;
164 if (fRawReader) fRawReader->Reset();
166 fSegmentation[0] = fSegmentation[1] = fSegmentation[2] = -1;
169 //_____________________________________________________________________________
170 Bool_t AliAltroRawStream::Next()
172 // read the next raw digit
173 // returns kFALSE if there is no digit left
175 fPrevDDLNumber = fDDLNumber;
177 fPrevHWAddress = fHWAddress;
180 while (fCount == 0) { // next trailer
181 if (fPosition <= 0) { // next payload
183 if (!fRawReader->ReadNextData(fData)) return kFALSE;
184 } while (fRawReader->GetDataSize() == 0);
186 fDDLNumber = fRawReader->GetDDLID();
188 fPosition = GetPosition();
196 if (fBunchLength == 0) ReadBunch();
204 //_____________________________________________________________________________
205 void AliAltroRawStream::SelectRawData(Int_t detId)
207 // Select the raw data for specific
209 AliDebug(1,Form("Selecting raw data for detector %d",detId));
210 fRawReader->Select(detId);
213 //_____________________________________________________________________________
214 void AliAltroRawStream::SelectRawData(const char *detName)
216 // Select the raw data for specific
218 AliDebug(1,Form("Selecting raw data for detector %s",detName));
219 fRawReader->Select(detName);
222 //_____________________________________________________________________________
223 UShort_t AliAltroRawStream::GetNextWord()
225 // Read the next 10 bit word in backward direction
226 // The input stream access is given by fData and fPosition
230 Int_t iBit = fPosition * 10;
231 Int_t iByte = iBit / 8;
232 Int_t shift = iBit % 8;
234 // the raw data is written as integers where the low bits are filled first
235 // -> little endian is assumed here !
236 Int_t iByteLow = iByte;
238 Int_t iByteHigh = iByte;
239 return ((fData[iByteHigh] * 256 + fData[iByteLow]) >> shift) & 0x03FF;
242 //_____________________________________________________________________________
243 Bool_t AliAltroRawStream::ReadTrailer()
245 //Read a trailer of 40 bits in the backward reading mode
246 //In case of no mapping is provided, read a dummy trailer
247 if (fNoAltroMapping) {
248 AliError("No ALTRO mapping information is loaded! Reading a dummy trailer!");
249 return ReadDummyTrailer();
252 //First reading filling words
254 Int_t nFillWords = 0;
255 while ((temp = GetNextWord()) == 0x2AA) nFillWords++;
256 if (nFillWords == 0) {
257 fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no 0x2AA");
259 AliWarning("Incorrect trailer found ! Expected 0x2AA not found !");
260 // trying to recover and find the next bunch
261 while ((fPosition > 5) && (temp != 0x2AA)) temp = GetNextWord();
263 fCount = fPosition = 0;
266 temp = GetNextWord();
269 //Then read the trailer
271 fRawReader->AddMajorErrorLog(kAltroTrailerErr,Form("size %d < 5",
274 AliWarning(Form("Incorrect raw data size ! Expected at least 5 words but found %d !",fPosition));
275 fCount = fPosition = 0;
279 fCount = (temp << 4) & 0x3FF;
280 if ((temp >> 6) != 0xA) {
281 fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no 0xA");
283 AliWarning(Form("Incorrect trailer found ! Expecting 0xA but found 0x%x !",temp >> 6));
288 temp = GetNextWord();
289 fHWAddress = (temp & 0x3) << 10;
290 if (((temp >> 2) & 0xF) != 0xA) {
291 fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no second 0xA");
293 AliWarning(Form("Incorrect trailer found ! Expecting second 0xA but found 0x%x !",(temp >> 2) & 0xF));
297 fCount |= ((temp & 0x3FF) >> 6);
298 if (fCount == 0) return kFALSE;
299 if (fCount >= fPosition) {
300 fRawReader->AddMajorErrorLog(kAltroTrailerErr,"invalid size");
302 AliWarning(Form("Incorrect trailer found ! The altro payload size is invalid (%d >= %d) !",fCount,fPosition));
306 temp = GetNextWord();
309 fPosition -= (4 - (fCount % 4)) % 4; // skip fill words
314 //_____________________________________________________________________________
315 Bool_t AliAltroRawStream::ReadDummyTrailer()
317 //Read a trailer of 40 bits in the backward reading mode
318 //In case of no mapping is provided, read a dummy trailer
320 while ((temp = GetNextWord()) == 0x2AA);
322 fSegmentation[0] = temp;
323 fSegmentation[1] = GetNextWord();
324 fSegmentation[2] = GetNextWord();
325 fCount = GetNextWord();
326 if (fCount == 0) return kFALSE;
329 fPosition -= (4 - (fCount % 4)) % 4; // skip fill words
334 //_____________________________________________________________________________
335 void AliAltroRawStream::ReadBunch()
337 // Read altro payload in
338 // backward direction
340 fRawReader->AddMinorErrorLog(kBunchLengthReadErr,"");
342 AliWarning(Form("Could not read bunch length and time bin ! Only %d 10-bit words are left !",fCount));
343 fBunchLength = fTimeBunch = fCount = 0;
347 fBunchLength = GetNextWord() - 2;
348 if (fBunchLength > fCount) {
349 fRawReader->AddMinorErrorLog(kBunchLengthReadErr,Form("bl=%d",fBunchLength));
351 AliWarning(Form("Could not read bunch length ! Bunch length = %d (>%d)",fBunchLength,fCount));
352 fBunchLength = fTimeBunch = fCount = 0;
355 fTimeBunch = fBunchLength;
358 fTime = GetNextWord();
364 //_____________________________________________________________________________
365 void AliAltroRawStream::ReadAmplitude()
367 // Read next time bin amplitude
369 fRawReader->AddMinorErrorLog(kAmplitudeReadErr,"");
371 AliWarning("Could not read sample amplitude !");
372 fCount = fSignal = fBunchLength = 0;
376 fSignal = GetNextWord();
384 //_____________________________________________________________________________
385 Int_t AliAltroRawStream::GetPosition()
387 // Sets the position in the
389 // Read the RCU trailer
390 // This includes the trailer size,
391 // RCU identifier and raw data payload.
392 // The RCU trailer format is described
393 // in details in the RCU manual.
395 // We use the last word of the payload
396 // in order to decide which RCU firmware
397 // was used during the data taking.
398 // The firmware v2 adds 0xAAAA as 16
399 // most significant bits and since the
400 // payload size (firmware v1) can not be
401 // that big, we use this as a unique
402 // label of the firmware version.
404 Int_t index = fRawReader->GetDataSize();
405 UInt_t word = Get32bitWord(index);
406 if (((word >> 16) == 0xaaaa) || (word == 2)) {
407 // This is RCU formware v2
408 // The statement word==2 is needed only temporary
409 // in order to be able to read previously generated
412 Int_t trailerSize = 0;
414 AliInfo("Old simulated raw data is assumed!");
419 // First read 32-bit word with the
420 // trailer size (7 bits), RCU ID (9 bits) and
421 // 0xAAA (the rest - 16 bits)
422 fRCUId = (Int_t)((word >> 7) & 0x1ff);
423 trailerSize = (word & 0x7F);
426 // Now read the beginning of the trailer
427 // where the payload size is written
428 if (trailerSize < 2) {
429 fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d bytes",
431 AliWarning(Form("Invalid trailer size found (%d bytes) !",
435 Int_t position = ReadRCUTrailer(index,trailerSize);
436 // The size is specified in a number of 40bits
437 // Therefore we need to transform it to number of bytes
440 // Check the consistency of the header and trailer
441 if (((fRawReader->GetDataSize() - trailerSize*4) < position) ||
442 ((fRawReader->GetDataSize() - trailerSize*4) >= (position + 4))) {
443 fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d tr=%d rcu=%d bytes",
444 fRawReader->GetDataSize(),
447 AliWarning(Form("Inconsistent raw data size ! Raw data size - %d bytes (from the header), RCU trailer - %d bytes, raw data paylod - %d bytes !",
448 fRawReader->GetDataSize(),
451 position = fRawReader->GetDataSize() - trailerSize*4;
454 return position * 8 / 10;
457 // In case of the Old RCU trailer format
458 // we have to read just the size of altro payload
459 // in units of 40-bit words
460 Int_t position = (Int_t)word;
464 fRCUTrailerData = NULL;
466 // The size is specified in a number of 40bits
467 // Therefore we need to transform it to number of bytes
470 if (!fIsShortDataHeader) {
472 // Check the consistency of the header and trailer
473 if (((fRawReader->GetDataSize() - 4) < position) ||
474 ((fRawReader->GetDataSize() - 4) >= (position + 4))) {
475 fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
476 fRawReader->GetDataSize()-4,
479 AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
480 fRawReader->GetDataSize()-4,
482 position = fRawReader->GetDataSize()-4;
486 // Check the consistency of the header and trailer
487 // In this case the header is shorter by 4 bytes
488 if ((fRawReader->GetDataSize() < position) ||
489 (fRawReader->GetDataSize() >= (position + 4))) {
490 fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
491 fRawReader->GetDataSize(),
494 AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
495 fRawReader->GetDataSize(),
497 position = fRawReader->GetDataSize();
500 // 7 32-bit words Common Data Header
501 // therefore we have to shift back by 4 bytes
502 // the pointer to the raw data payload
506 // Return the position in units of 10-bit words
507 return position*8/10;
511 //_____________________________________________________________________________
512 UInt_t AliAltroRawStream::Get32bitWord(Int_t &index)
514 // This method returns the 32 bit word at a given
515 // position inside the raw data payload.
516 // The 'index' points to the beginning of the next word.
517 // The method is supposed to be endian (platform)
521 AliFatal("Raw data paylod buffer is not yet initialized !");
525 fRawReader->AddFatalErrorLog(k32bitWordReadErr,Form("pos = %d",index));
527 AliWarning(Form("Invalid raw data payload position (%d) !",index));
531 word = fData[--index] << 24;
532 word |= fData[--index] << 16;
533 word |= fData[--index] << 8;
534 word |= fData[--index];
539 //_____________________________________________________________________________
540 Int_t AliAltroRawStream::ReadRCUTrailer(Int_t &index, Int_t trailerSize)
542 // The method decodes the RCU trailer data
543 // according to the RCU fw ver.2 specs
545 fRCUTrailerSize = trailerSize*4;
547 for (trailerSize -= 2; trailerSize > 0; trailerSize--) {
548 Int_t word = Get32bitWord(index);
549 Int_t parCode = word >> 26;
550 Int_t parData = word & 0x3FFFFFF;
554 fFECERRA = ((parData >> 13) & 0x1FFF) << 7;
555 fFECERRB = ((parData & 0x1FFF)) << 7;
559 fERRREG2 = parData & 0x1FF;
563 if (parData != 0xAAAAAA) {
564 fRawReader->AddMinorErrorLog(kRCUTrailerErr,"no 0xAAAAAA");
565 AliWarning(Form("Parameter code %d : no 0xAAAAAA found !",
571 if (parData != 0xAAAAAA) {
572 fRawReader->AddMinorErrorLog(kRCUTrailerErr,"no 0xAAAAAA");
573 AliWarning(Form("Parameter code %d : no 0xAAAAAA found !",
579 fActiveFECsA = parData & 0xFFFF;
583 fActiveFECsB = parData & 0xFFFF;
587 fAltroCFG1 = parData & 0x7FFFF;
591 fAltroCFG2 = parData & 0x1FFFFFF;
594 fRawReader->AddMinorErrorLog(kRCUTrailerErr,"undef word");
595 AliWarning(Form("Undefined parameter code %d, ignore it !",
602 fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d raw=%d bytes",
604 fRawReader->GetDataSize()));
605 AliWarning(Form("Invalid trailer size found (%d bytes) ! The size is bigger than the raw data size (%d bytes)!",
607 fRawReader->GetDataSize()));
609 fRCUTrailerSize = trailerSize*4;
610 fRCUTrailerData = fData + index;
612 Int_t position = Get32bitWord(index);
618 //_____________________________________________________________________________
619 Double_t AliAltroRawStream::GetTSample() const
621 // Returns the sampling time
622 // in seconds. In case the rcu trailer
623 // was note read, return an invalid number (0)
625 if (!fRCUTrailerData) return 0.;
627 const Double_t kLHCTimeSample = 25.0e-9; // LHC clocks runs at 40 MHz
628 UChar_t fq = (fAltroCFG2 >> 5) & 0xF;
633 tSample = 2.0*kLHCTimeSample;
637 tSample = 4.0*kLHCTimeSample;
641 tSample = 8.0*kLHCTimeSample;
644 AliWarning(Form("Invalid sampling frequency value %d !",
653 //_____________________________________________________________________________
654 Double_t AliAltroRawStream::GetL1Phase() const
656 // Returns the L1 phase w.r.t to the
658 if (!fRCUTrailerData) return 0.;
660 const Double_t kLHCTimeSample = 25.0e-9; // LHC clocks runs at 40 MHz
661 Double_t phase = ((Double_t)(fAltroCFG2 & 0x1F))*kLHCTimeSample;
663 Double_t tSample = GetTSample();
664 if (phase >= tSample) {
665 AliWarning(Form("Invalid L1 trigger phase (%f >= %d) !",
673 //_____________________________________________________________________________
674 void AliAltroRawStream::PrintRCUTrailer() const
676 // Prints the contents of
677 // the RCU trailer data
678 printf("RCU trailer:\n===========\n");
679 printf("FECERRA: 0x%x\nFECERRB: 0x%x\n",fFECERRA,fFECERRB);
680 printf("ERRREG2: 0x%x\n",fERRREG2);
681 printf("Active FECs (branch A): 0x%x\nActive FECs (branch B): 0x%x\n",fActiveFECsA,fActiveFECsB);
682 printf("Baseline corr: 0x%x\n",GetBaselineCorr());
683 printf("Number of presamples: %d\nNumber of postsamples: %d\n",GetNPresamples(),GetNPostsamples());
684 printf("Second baseline corr: %d\n",GetSecondBaselineCorr());
685 printf("GlitchFilter: %d\n",GetGlitchFilter());
686 printf("Number of non-ZS postsamples: %d\nNumber of non-ZS presamples: %d\n",GetNNonZSPostsamples(),GetNNonZSPresamples());
687 printf("Number of ALTRO buffers: %d\n",GetNAltroBuffers());
688 printf("Number of pretrigger samples: %d\n",GetNPretriggerSamples());
689 printf("Number of samples per channel: %d\n",GetNSamplesPerCh());
690 printf("Sparse readout: %d\n",GetSparseRO());
691 printf("Sampling time: %f s\n",GetTSample());
692 printf("L1 Phase: %f s\n",GetL1Phase());
693 printf("===========\n");
696 //_____________________________________________________________________________
697 Bool_t AliAltroRawStream::GetRCUTrailerData(UChar_t*& data) const
699 // Return a pointer to the RCU trailer
700 // data. Should be called always after
701 // the RCU trailer was already processed
702 // in the GetPosition() method
703 if (!fRCUTrailerSize || !fRCUTrailerData) {
704 AliError("No valid RCU trailer data is found !");
709 data = fRCUTrailerData;
714 //_____________________________________________________________________________
715 void AliAltroRawStream::PrintDebug() const
717 // The method prints all the available
718 // debug information.
719 // Its is used in case of decoding errors.
721 AliError("Start of debug printout\n--------------------");
724 if (fRawReader) fRawReader->Dump();
726 AliError("End of debug printout\n--------------------");
729 //_____________________________________________________________________________
730 Int_t AliAltroRawStream::GetBranch() const
732 // The method provides the RCU branch index (0 or 1)
733 // for the current hardware address.
734 // In case the hardware address has not been yet
735 // initialized, the method returns -1
736 if (fHWAddress == -1) return -1;
738 return ((fHWAddress >> 11) & 0x1);
741 //_____________________________________________________________________________
742 Int_t AliAltroRawStream::GetFEC() const
744 // The method provides the front-end card index
745 // for the current hardware address.
746 // In case the hardware address has not been yet
747 // initialized, the method returns -1
748 if (fHWAddress == -1) return -1;
750 return ((fHWAddress >> 7) & 0xF);
753 //_____________________________________________________________________________
754 Int_t AliAltroRawStream::GetAltro() const
756 // The method provides the altro chip index
757 // for the current hardware address.
758 // In case the hardware address has not been yet
759 // initialized, the method returns -1
760 if (fHWAddress == -1) return -1;
762 return ((fHWAddress >> 4) & 0x7);
765 //_____________________________________________________________________________
766 Int_t AliAltroRawStream::GetChannel() const
768 // The method provides the channel index
769 // for the current hardware address.
770 // In case the hardware address has not been yet
771 // initialized, the method returns -1
772 if (fHWAddress == -1) return -1;
774 return (fHWAddress & 0xF);
777 //_____________________________________________________________________________
778 void AliAltroRawStream::AddMappingErrorLog(const char *message)
780 // Signal a mapping error
781 // The method can be used by the TPC,PHOS,EMCAL,FMD raw stream
782 // classes in order to log an error related to bad altro mapping
784 if (fRawReader) fRawReader->AddMinorErrorLog(kBadAltroMapping,message);