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 fIsShortDataHeader(kFALSE),
49 fRawReader(rawReader),
54 fRCUTrailerData(NULL),
66 // create an object to read Altro raw digits
69 //_____________________________________________________________________________
70 AliAltroRawStream::AliAltroRawStream(const AliAltroRawStream& stream) :
72 fIsShortDataHeader(stream.fIsShortDataHeader),
73 fDDLNumber(stream.fDDLNumber),
74 fPrevDDLNumber(stream.fPrevDDLNumber),
75 fRCUId(stream.fRCUId),
76 fPrevRCUId(stream.fPrevRCUId),
77 fHWAddress(stream.fHWAddress),
78 fPrevHWAddress(stream.fPrevHWAddress),
80 fPrevTime(stream.fPrevTime),
81 fSignal(stream.fSignal),
82 fTimeBunch(stream.fTimeBunch),
83 fRawReader(stream.fRawReader),
85 fPosition(stream.fPosition),
86 fCount(stream.fCount),
87 fBunchLength(stream.fBunchLength),
88 fRCUTrailerData(stream.fRCUTrailerData),
89 fRCUTrailerSize(stream.fRCUTrailerSize),
90 fFECERRA(stream.fFECERRA),
91 fFECERRB(stream.fFECERRB),
92 fERRREG2(stream.fERRREG2),
93 fERRREG3(stream.fERRREG3),
94 fERRREG4(stream.fERRREG4),
95 fActiveFECsA(stream.fActiveFECsA),
96 fActiveFECsB(stream.fActiveFECsB),
97 fAltroCFG1(stream.fAltroCFG1),
98 fAltroCFG2(stream.fAltroCFG2)
102 //_____________________________________________________________________________
103 AliAltroRawStream& AliAltroRawStream::operator = (const AliAltroRawStream& stream)
105 if(&stream == this) return *this;
107 fIsShortDataHeader = stream.fIsShortDataHeader;
108 fDDLNumber = stream.fDDLNumber;
109 fPrevDDLNumber = stream.fPrevDDLNumber;
110 fRCUId = stream.fRCUId;
111 fPrevRCUId = stream.fPrevRCUId;
112 fHWAddress = stream.fHWAddress;
113 fPrevHWAddress = stream.fPrevHWAddress;
114 fTime = stream.fTime;
115 fPrevTime = stream.fPrevTime;
116 fSignal = stream.fSignal;
117 fTimeBunch = stream.fTimeBunch;
118 fRawReader = stream.fRawReader;
119 fData = stream.fData;
120 fPosition = stream.fPosition;
121 fCount = stream.fCount;
122 fBunchLength = stream.fBunchLength;
123 fRCUTrailerData = stream.fRCUTrailerData;
124 fRCUTrailerSize = stream.fRCUTrailerSize;
125 fFECERRA = stream.fFECERRA;
126 fFECERRB = stream.fFECERRB;
127 fERRREG2 = stream.fERRREG2;
128 fERRREG3 = stream.fERRREG3;
129 fERRREG4 = stream.fERRREG4;
130 fActiveFECsA = stream.fActiveFECsA;
131 fActiveFECsB = stream.fActiveFECsB;
132 fAltroCFG1 = stream.fAltroCFG1;
133 fAltroCFG2 = stream.fAltroCFG2;
138 //_____________________________________________________________________________
139 AliAltroRawStream::~AliAltroRawStream()
145 //_____________________________________________________________________________
146 void AliAltroRawStream::Reset()
148 // reset altro raw stream params
150 fPosition = fCount = fBunchLength = 0;
152 fRCUTrailerData = NULL;
155 fFECERRA = fFECERRB = fERRREG2 = fERRREG3 = fERRREG4 = fActiveFECsA = fActiveFECsB = fAltroCFG1 = fAltroCFG2 = 0;
157 fDDLNumber = fPrevDDLNumber = fRCUId = fPrevRCUId = fHWAddress = fPrevHWAddress = fTime = fPrevTime = fSignal = fTimeBunch = -1;
159 if (fRawReader) fRawReader->Reset();
162 //_____________________________________________________________________________
163 Bool_t AliAltroRawStream::Next()
165 // read the next raw digit
166 // returns kFALSE if there is no digit left
168 fPrevDDLNumber = fDDLNumber;
170 fPrevHWAddress = fHWAddress;
173 while (fCount == 0) { // next trailer
174 while (fPosition <= 0) { // next payload
176 if (!fRawReader->ReadNextData(fData)) return kFALSE;
177 } while (fRawReader->GetDataSize() == 0);
179 fDDLNumber = fRawReader->GetDDLID();
181 fPosition = GetPosition();
189 if (fBunchLength == 0) ReadBunch();
197 //_____________________________________________________________________________
198 Bool_t AliAltroRawStream::NextDDL(UChar_t *data)
202 if (!fRawReader->ReadNextData(fData)) return kFALSE;
203 } while (fRawReader->GetDataSize() == 0);
209 fDDLNumber = fRawReader->GetDDLID();
210 fPosition = GetPosition();
215 //_____________________________________________________________________________
216 Bool_t AliAltroRawStream::NextChannel()
218 if (fPosition <= 0) return kFALSE;
225 //_____________________________________________________________________________
226 Bool_t AliAltroRawStream::NextBunch(UShort_t *bunchData,
230 if (fCount == 0) return kFALSE;
233 bunchLength = fTimeBunch;
234 startTimeBin = fTime;
236 while (fBunchLength > 0) {
238 bunchData[bunchLength-fBunchLength-1] = fSignal;
244 //_____________________________________________________________________________
245 void AliAltroRawStream::SelectRawData(Int_t detId)
247 // Select the raw data for specific
249 AliDebug(1,Form("Selecting raw data for detector %d",detId));
250 fRawReader->Select(detId);
253 //_____________________________________________________________________________
254 void AliAltroRawStream::SelectRawData(const char *detName)
256 // Select the raw data for specific
258 AliDebug(1,Form("Selecting raw data for detector %s",detName));
259 fRawReader->Select(detName);
262 //_____________________________________________________________________________
263 UShort_t AliAltroRawStream::GetNextWord()
265 // Read the next 10 bit word in backward direction
266 // The input stream access is given by fData and fPosition
270 Int_t iBit = fPosition * 10;
271 Int_t iByte = iBit / 8;
272 Int_t shift = iBit % 8;
274 // the raw data is written as integers where the low bits are filled first
275 // -> little endian is assumed here !
276 Int_t iByteLow = iByte;
278 Int_t iByteHigh = iByte;
279 return ((fData[iByteHigh] * 256 + fData[iByteLow]) >> shift) & 0x03FF;
282 //_____________________________________________________________________________
283 Bool_t AliAltroRawStream::ReadTrailer()
285 //Read a trailer of 40 bits in the backward reading mode
286 //First reading filling words
288 Int_t nFillWords = 0;
289 while ((temp = GetNextWord()) == 0x2AA) nFillWords++;
290 if (nFillWords == 0) {
291 fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no 0x2AA");
293 AliWarning(Form("Incorrect trailer found ! Expected 0x2AA not found (0x%x != 0x2AA) ! Current position %d, DDL=%d",
294 temp,fPosition,fDDLNumber));
295 // trying to recover and find the next bunch
296 while ((fPosition > 2) && (temp != 0x2AA)) temp = GetNextWord();
298 fCount = fPosition = 0;
301 temp = GetNextWord();
304 //Then read the trailer
306 fRawReader->AddMajorErrorLog(kAltroTrailerErr,Form("size %d < 5",
309 AliWarning(Form("Incorrect raw data size ! Expected at least 5 words but found %d !",fPosition));
310 fCount = fPosition = 0;
314 fCount = (temp << 4) & 0x3FF;
315 if ((temp >> 6) != 0xA) {
316 fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no 0xA");
318 AliWarning(Form("Incorrect trailer found ! Expecting 0xA but found 0x%x !",temp >> 6));
323 temp = GetNextWord();
324 fHWAddress = (temp & 0x3) << 10;
325 if (((temp >> 2) & 0xF) != 0xA) {
326 fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no second 0xA");
328 AliWarning(Form("Incorrect trailer found ! Expecting second 0xA but found 0x%x !",(temp >> 2) & 0xF));
332 fCount |= ((temp & 0x3FF) >> 6);
334 if (fCount >= fPosition) {
335 fRawReader->AddMajorErrorLog(kAltroTrailerErr,"invalid size");
337 AliWarning(Form("Incorrect trailer found ! The altro payload size is invalid (%d >= %d) !",fCount,fPosition));
341 temp = GetNextWord();
344 fPosition -= (4 - (fCount % 4)) % 4; // skip fill words
349 //_____________________________________________________________________________
350 void AliAltroRawStream::ReadBunch()
352 // Read altro payload in
353 // backward direction
355 fRawReader->AddMinorErrorLog(kBunchLengthReadErr,"");
357 AliWarning(Form("Could not read bunch length and time bin ! Only %d 10-bit words are left !",fCount));
358 fBunchLength = fTimeBunch = fCount = 0;
362 fBunchLength = GetNextWord() - 2;
363 if (fBunchLength > fCount) {
364 fRawReader->AddMinorErrorLog(kBunchLengthReadErr,Form("bl=%d",fBunchLength));
366 AliWarning(Form("Could not read bunch length ! Bunch length = %d (>%d)",fBunchLength,fCount));
367 fBunchLength = fTimeBunch = fCount = 0;
370 fTimeBunch = fBunchLength;
373 fTime = GetNextWord();
379 //_____________________________________________________________________________
380 void AliAltroRawStream::ReadAmplitude()
382 // Read next time bin amplitude
384 fRawReader->AddMinorErrorLog(kAmplitudeReadErr,"");
386 AliWarning("Could not read sample amplitude !");
387 fCount = fSignal = fBunchLength = 0;
391 fSignal = GetNextWord();
399 //_____________________________________________________________________________
400 Int_t AliAltroRawStream::GetPosition()
402 // Sets the position in the
404 // Read the RCU trailer
405 // This includes the trailer size,
406 // RCU identifier and raw data payload.
407 // The RCU trailer format is described
408 // in details in the RCU manual.
410 // We use the last word of the payload
411 // in order to decide which RCU firmware
412 // was used during the data taking.
413 // The firmware v2 adds 0xAAAA as 16
414 // most significant bits and since the
415 // payload size (firmware v1) can not be
416 // that big, we use this as a unique
417 // label of the firmware version.
419 Int_t index = fRawReader->GetDataSize();
420 UInt_t word = Get32bitWord(index);
421 if (((word >> 16) == 0xaaaa) || (word == 2)) {
422 // This is RCU formware v2
423 // The statement word==2 is needed only temporary
424 // in order to be able to read previously generated
427 Int_t trailerSize = 0;
429 AliInfo("Old simulated raw data is assumed!");
434 // First read 32-bit word with the
435 // trailer size (7 bits), RCU ID (9 bits) and
436 // 0xAAA (the rest - 16 bits)
437 fRCUId = (Int_t)((word >> 7) & 0x1ff);
438 trailerSize = (word & 0x7F);
441 // Now read the beginning of the trailer
442 // where the payload size is written
443 if (trailerSize < 2) {
444 fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d bytes",
446 AliWarning(Form("Invalid trailer size found (%d bytes) !",
450 Int_t position = ReadRCUTrailer(index,trailerSize);
451 // The size is specified in a number of 40bits
452 // Therefore we need to transform it to number of bytes
455 // Check the consistency of the header and trailer
456 if (((fRawReader->GetDataSize() - trailerSize*4) < position) ||
457 ((fRawReader->GetDataSize() - trailerSize*4) >= (position + 4))) {
458 fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d tr=%d rcu=%d bytes",
459 fRawReader->GetDataSize(),
462 AliWarning(Form("Inconsistent raw data size ! Raw data size - %d bytes (from the header), RCU trailer - %d bytes, raw data paylod - %d bytes !",
463 fRawReader->GetDataSize(),
466 position = fRawReader->GetDataSize() - trailerSize*4;
469 return position * 8 / 10;
472 // In case of the Old RCU trailer format
473 // we have to read just the size of altro payload
474 // in units of 40-bit words
475 Int_t position = (Int_t)word;
479 fRCUTrailerData = NULL;
481 // The size is specified in a number of 40bits
482 // Therefore we need to transform it to number of bytes
485 if (!fIsShortDataHeader) {
487 // Check the consistency of the header and trailer
488 if (((fRawReader->GetDataSize() - 4) < position) ||
489 ((fRawReader->GetDataSize() - 4) >= (position + 4))) {
490 fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
491 fRawReader->GetDataSize()-4,
494 AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
495 fRawReader->GetDataSize()-4,
497 position = fRawReader->GetDataSize()-4;
501 // Check the consistency of the header and trailer
502 // In this case the header is shorter by 4 bytes
503 if ((fRawReader->GetDataSize() < position) ||
504 (fRawReader->GetDataSize() >= (position + 4))) {
505 fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
506 fRawReader->GetDataSize(),
509 AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
510 fRawReader->GetDataSize(),
512 position = fRawReader->GetDataSize();
515 // 7 32-bit words Common Data Header
516 // therefore we have to shift back by 4 bytes
517 // the pointer to the raw data payload
521 // Return the position in units of 10-bit words
522 return position*8/10;
526 //_____________________________________________________________________________
527 UInt_t AliAltroRawStream::Get32bitWord(Int_t &index)
529 // This method returns the 32 bit word at a given
530 // position inside the raw data payload.
531 // The 'index' points to the beginning of the next word.
532 // The method is supposed to be endian (platform)
536 AliFatal("Raw data paylod buffer is not yet initialized !");
540 fRawReader->AddFatalErrorLog(k32bitWordReadErr,Form("pos = %d",index));
542 AliWarning(Form("Invalid raw data payload position (%d) !",index));
546 word = fData[--index] << 24;
547 word |= fData[--index] << 16;
548 word |= fData[--index] << 8;
549 word |= fData[--index];
554 //_____________________________________________________________________________
555 Int_t AliAltroRawStream::ReadRCUTrailer(Int_t &index, Int_t trailerSize)
557 // The method decodes the RCU trailer data
558 // according to the RCU fw ver.2 specs
560 fRCUTrailerSize = trailerSize*4;
562 for (trailerSize -= 2; trailerSize > 0; trailerSize--) {
563 Int_t word = Get32bitWord(index);
564 Int_t parCode = word >> 26;
565 Int_t parData = word & 0x3FFFFFF;
569 fFECERRA = ((parData >> 13) & 0x1FFF) << 7;
570 fFECERRB = ((parData & 0x1FFF)) << 7;
574 fERRREG2 = parData & 0x1FF;
578 fERRREG3 = parData & 0xFFF;
582 fERRREG4 = parData & 0xFFF;
586 fActiveFECsA = parData & 0xFFFF;
590 fActiveFECsB = parData & 0xFFFF;
594 fAltroCFG1 = parData & 0xFFFFF;
598 fAltroCFG2 = parData & 0x1FFFFFF;
601 fRawReader->AddMinorErrorLog(kRCUTrailerErr,"undef word");
602 AliWarning(Form("Undefined parameter code %d, ignore it !",
609 fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d raw=%d bytes",
611 fRawReader->GetDataSize()));
612 AliWarning(Form("Invalid trailer size found (%d bytes) ! The size is bigger than the raw data size (%d bytes)!",
614 fRawReader->GetDataSize()));
616 fRCUTrailerData = fData + index;
618 Int_t position = Get32bitWord(index);
624 //_____________________________________________________________________________
625 Double_t AliAltroRawStream::GetTSample() const
627 // Returns the sampling time
628 // in seconds. In case the rcu trailer
629 // was note read, return an invalid number (0)
631 if (!fRCUTrailerData) return 0.;
633 const Double_t kLHCTimeSample = 25.0e-9; // LHC clocks runs at 40 MHz
634 UChar_t fq = (fAltroCFG2 >> 5) & 0xF;
639 tSample = 2.0*kLHCTimeSample;
643 tSample = 4.0*kLHCTimeSample;
647 tSample = 8.0*kLHCTimeSample;
650 AliWarning(Form("Invalid sampling frequency value %d !",
659 //_____________________________________________________________________________
660 Double_t AliAltroRawStream::GetL1Phase() const
662 // Returns the L1 phase w.r.t to the
664 if (!fRCUTrailerData) return 0.;
666 const Double_t kLHCTimeSample = 25.0e-9; // LHC clocks runs at 40 MHz
667 Double_t phase = ((Double_t)(fAltroCFG2 & 0x1F))*kLHCTimeSample;
669 Double_t tSample = GetTSample();
670 if (phase >= tSample) {
671 AliWarning(Form("Invalid L1 trigger phase (%f >= %d) !",
679 //_____________________________________________________________________________
680 void AliAltroRawStream::PrintRCUTrailer() const
682 // Prints the contents of
683 // the RCU trailer data
684 printf("RCU trailer:\n===========\n");
685 printf("FECERRA: 0x%x\nFECERRB: 0x%x\n",fFECERRA,fFECERRB);
686 printf("ERRREG2: 0x%x\n",fERRREG2);
687 printf("#channels skipped due to address mismatch: %d\n",GetNChAddrMismatch());
688 printf("#channels skipped due to bad block length: %d\n",GetNChLengthMismatch());
689 printf("Active FECs (branch A): 0x%x\nActive FECs (branch B): 0x%x\n",fActiveFECsA,fActiveFECsB);
690 printf("Baseline corr: 0x%x\n",GetBaselineCorr());
691 printf("Number of presamples: %d\nNumber of postsamples: %d\n",GetNPresamples(),GetNPostsamples());
692 printf("Second baseline corr: %d\n",GetSecondBaselineCorr());
693 printf("GlitchFilter: %d\n",GetGlitchFilter());
694 printf("Number of non-ZS postsamples: %d\nNumber of non-ZS presamples: %d\n",GetNNonZSPostsamples(),GetNNonZSPresamples());
695 printf("Number of ALTRO buffers: %d\n",GetNAltroBuffers());
696 printf("Number of pretrigger samples: %d\n",GetNPretriggerSamples());
697 printf("Number of samples per channel: %d\n",GetNSamplesPerCh());
698 printf("Sparse readout: %d\n",GetSparseRO());
699 printf("Sampling time: %e s\n",GetTSample());
700 printf("L1 Phase: %e s\n",GetL1Phase());
701 printf("AltroCFG1: 0x%x\nAltroCFG2: 0x%x\n",GetAltroCFG1(),GetAltroCFG2());
702 printf("===========\n");
705 //_____________________________________________________________________________
706 Bool_t AliAltroRawStream::GetRCUTrailerData(UChar_t*& data) const
708 // Return a pointer to the RCU trailer
709 // data. Should be called always after
710 // the RCU trailer was already processed
711 // in the GetPosition() method
712 if (!fRCUTrailerSize || !fRCUTrailerData) {
713 AliError("No valid RCU trailer data is found !");
718 data = fRCUTrailerData;
723 //_____________________________________________________________________________
724 void AliAltroRawStream::PrintDebug() const
726 // The method prints all the available
727 // debug information.
728 // Its is used in case of decoding errors.
730 AliError("Start of debug printout\n--------------------");
733 if (fRawReader) fRawReader->Dump();
735 AliError("End of debug printout\n--------------------");
738 //_____________________________________________________________________________
739 Int_t AliAltroRawStream::GetBranch() const
741 // The method provides the RCU branch index (0 or 1)
742 // for the current hardware address.
743 // In case the hardware address has not been yet
744 // initialized, the method returns -1
745 if (fHWAddress == -1) return -1;
747 return ((fHWAddress >> 11) & 0x1);
750 //_____________________________________________________________________________
751 Int_t AliAltroRawStream::GetFEC() const
753 // The method provides the front-end card index
754 // for the current hardware address.
755 // In case the hardware address has not been yet
756 // initialized, the method returns -1
757 if (fHWAddress == -1) return -1;
759 return ((fHWAddress >> 7) & 0xF);
762 //_____________________________________________________________________________
763 Int_t AliAltroRawStream::GetAltro() const
765 // The method provides the altro chip index
766 // for the current hardware address.
767 // In case the hardware address has not been yet
768 // initialized, the method returns -1
769 if (fHWAddress == -1) return -1;
771 return ((fHWAddress >> 4) & 0x7);
774 //_____________________________________________________________________________
775 Int_t AliAltroRawStream::GetChannel() const
777 // The method provides the channel index
778 // for the current hardware address.
779 // In case the hardware address has not been yet
780 // initialized, the method returns -1
781 if (fHWAddress == -1) return -1;
783 return (fHWAddress & 0xF);
786 //_____________________________________________________________________________
787 void AliAltroRawStream::AddMappingErrorLog(const char *message)
789 // Signal a mapping error
790 // The method can be used by the TPC,PHOS,EMCAL,FMD raw stream
791 // classes in order to log an error related to bad altro mapping
793 if (fRawReader) fRawReader->AddMinorErrorLog(kBadAltroMapping,message);