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),
58 // create an object to read Altro raw digits
59 fSegmentation[0] = fSegmentation[1] = fSegmentation[2] = -1;
62 //_____________________________________________________________________________
63 AliAltroRawStream::AliAltroRawStream(const AliAltroRawStream& stream) :
65 fNoAltroMapping(stream.fNoAltroMapping),
66 fIsShortDataHeader(stream.fIsShortDataHeader),
67 fDDLNumber(stream.fDDLNumber),
68 fPrevDDLNumber(stream.fPrevDDLNumber),
69 fRCUId(stream.fRCUId),
70 fPrevRCUId(stream.fPrevRCUId),
71 fHWAddress(stream.fHWAddress),
72 fPrevHWAddress(stream.fPrevHWAddress),
74 fPrevTime(stream.fPrevTime),
75 fSignal(stream.fSignal),
76 fTimeBunch(stream.fTimeBunch),
77 fRawReader(stream.fRawReader),
79 fPosition(stream.fPosition),
80 fCount(stream.fCount),
81 fBunchLength(stream.fBunchLength),
82 fRCUTrailerData(stream.fRCUTrailerData),
83 fRCUTrailerSize(stream.fRCUTrailerSize)
85 fSegmentation[0] = stream.fSegmentation[0];
86 fSegmentation[1] = stream.fSegmentation[1];
87 fSegmentation[2] = stream.fSegmentation[2];
90 //_____________________________________________________________________________
91 AliAltroRawStream& AliAltroRawStream::operator = (const AliAltroRawStream& stream)
93 if(&stream == this) return *this;
95 fNoAltroMapping = stream.fNoAltroMapping;
96 fIsShortDataHeader = stream.fIsShortDataHeader;
97 fDDLNumber = stream.fDDLNumber;
98 fPrevDDLNumber = stream.fPrevDDLNumber;
99 fRCUId = stream.fRCUId;
100 fPrevRCUId = stream.fPrevRCUId;
101 fHWAddress = stream.fHWAddress;
102 fPrevHWAddress = stream.fPrevHWAddress;
103 fTime = stream.fTime;
104 fPrevTime = stream.fPrevTime;
105 fSignal = stream.fSignal;
106 fTimeBunch = stream.fTimeBunch;
107 fRawReader = stream.fRawReader;
108 fData = stream.fData;
109 fPosition = stream.fPosition;
110 fCount = stream.fCount;
111 fBunchLength = stream.fBunchLength;
112 fRCUTrailerData = stream.fRCUTrailerData;
113 fRCUTrailerSize = stream.fRCUTrailerSize;
115 fSegmentation[0] = stream.fSegmentation[0];
116 fSegmentation[1] = stream.fSegmentation[1];
117 fSegmentation[2] = stream.fSegmentation[2];
122 //_____________________________________________________________________________
123 AliAltroRawStream::~AliAltroRawStream()
129 //_____________________________________________________________________________
130 void AliAltroRawStream::Reset()
132 // reset altro raw stream params
134 fPosition = fCount = fBunchLength = 0;
136 fRCUTrailerData = NULL;
139 fDDLNumber = fPrevDDLNumber = fRCUId = fPrevRCUId = fHWAddress = fPrevHWAddress = fTime = fPrevTime = fSignal = fTimeBunch = -1;
141 if (fRawReader) fRawReader->Reset();
143 fSegmentation[0] = fSegmentation[1] = fSegmentation[2] = -1;
146 //_____________________________________________________________________________
147 Bool_t AliAltroRawStream::Next()
149 // read the next raw digit
150 // returns kFALSE if there is no digit left
152 fPrevDDLNumber = fDDLNumber;
154 fPrevHWAddress = fHWAddress;
157 while (fCount == 0) { // next trailer
158 if (fPosition <= 0) { // next payload
160 if (!fRawReader->ReadNextData(fData)) return kFALSE;
161 } while (fRawReader->GetDataSize() == 0);
163 fDDLNumber = fRawReader->GetDDLID();
165 fPosition = GetPosition();
173 if (fBunchLength == 0) ReadBunch();
181 //_____________________________________________________________________________
182 void AliAltroRawStream::SelectRawData(Int_t detId)
184 // Select the raw data for specific
186 AliDebug(1,Form("Selecting raw data for detector %d",detId));
187 fRawReader->Select(detId);
190 //_____________________________________________________________________________
191 void AliAltroRawStream::SelectRawData(const char *detName)
193 // Select the raw data for specific
195 AliDebug(1,Form("Selecting raw data for detector %s",detName));
196 fRawReader->Select(detName);
199 //_____________________________________________________________________________
200 UShort_t AliAltroRawStream::GetNextWord()
202 // Read the next 10 bit word in backward direction
203 // The input stream access is given by fData and fPosition
207 Int_t iBit = fPosition * 10;
208 Int_t iByte = iBit / 8;
209 Int_t shift = iBit % 8;
211 // the raw data is written as integers where the low bits are filled first
212 // -> little endian is assumed here !
213 Int_t iByteLow = iByte;
215 Int_t iByteHigh = iByte;
216 return ((fData[iByteHigh] * 256 + fData[iByteLow]) >> shift) & 0x03FF;
219 //_____________________________________________________________________________
220 Bool_t AliAltroRawStream::ReadTrailer()
222 //Read a trailer of 40 bits in the backward reading mode
223 //In case of no mapping is provided, read a dummy trailer
224 if (fNoAltroMapping) {
225 AliError("No ALTRO mapping information is loaded! Reading a dummy trailer!");
226 return ReadDummyTrailer();
229 //First reading filling words
231 Int_t nFillWords = 0;
232 while ((temp = GetNextWord()) == 0x2AA) nFillWords++;
233 if (nFillWords == 0) {
234 fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no 0x2AA");
236 AliWarning("Incorrect trailer found ! Expected 0x2AA not found !");
237 // trying to recover and find the next bunch
238 while ((fPosition > 5) && (temp != 0x2AA)) temp = GetNextWord();
240 fCount = fPosition = 0;
243 temp = GetNextWord();
246 //Then read the trailer
248 fRawReader->AddMajorErrorLog(kAltroTrailerErr,Form("size %d < 5",
251 AliWarning(Form("Incorrect raw data size ! Expected at least 5 words but found %d !",fPosition));
252 fCount = fPosition = 0;
256 fCount = (temp << 4) & 0x3FF;
257 if ((temp >> 6) != 0xA) {
258 fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no 0xA");
260 AliWarning(Form("Incorrect trailer found ! Expecting 0xA but found 0x%x !",temp >> 6));
265 temp = GetNextWord();
266 fHWAddress = (temp & 0x3) << 10;
267 if (((temp >> 2) & 0xF) != 0xA) {
268 fRawReader->AddMajorErrorLog(kAltroTrailerErr,"no second 0xA");
270 AliWarning(Form("Incorrect trailer found ! Expecting second 0xA but found 0x%x !",(temp >> 2) & 0xF));
274 fCount |= ((temp & 0x3FF) >> 6);
275 if (fCount == 0) return kFALSE;
276 if (fCount >= fPosition) {
277 fRawReader->AddMajorErrorLog(kAltroTrailerErr,"invalid size");
279 AliWarning(Form("Incorrect trailer found ! The altro payload size is invalid (%d >= %d) !",fCount,fPosition));
283 temp = GetNextWord();
286 fPosition -= (4 - (fCount % 4)) % 4; // skip fill words
291 //_____________________________________________________________________________
292 Bool_t AliAltroRawStream::ReadDummyTrailer()
294 //Read a trailer of 40 bits in the backward reading mode
295 //In case of no mapping is provided, read a dummy trailer
297 while ((temp = GetNextWord()) == 0x2AA);
299 fSegmentation[0] = temp;
300 fSegmentation[1] = GetNextWord();
301 fSegmentation[2] = GetNextWord();
302 fCount = GetNextWord();
303 if (fCount == 0) return kFALSE;
306 fPosition -= (4 - (fCount % 4)) % 4; // skip fill words
311 //_____________________________________________________________________________
312 void AliAltroRawStream::ReadBunch()
314 // Read altro payload in
315 // backward direction
317 fRawReader->AddMinorErrorLog(kBunchLengthReadErr,"");
319 AliWarning(Form("Could not read bunch length and time bin ! Only %d 10-bit words are left !",fCount));
320 fBunchLength = fTimeBunch = fCount = 0;
324 fBunchLength = GetNextWord() - 2;
325 if (fBunchLength > fCount) {
326 fRawReader->AddMinorErrorLog(kBunchLengthReadErr,Form("bl=%d",fBunchLength));
328 AliWarning(Form("Could not read bunch length ! Bunch length = %d (>%d)",fBunchLength,fCount));
329 fBunchLength = fTimeBunch = fCount = 0;
332 fTimeBunch = fBunchLength;
335 fTime = GetNextWord();
341 //_____________________________________________________________________________
342 void AliAltroRawStream::ReadAmplitude()
344 // Read next time bin amplitude
346 fRawReader->AddMinorErrorLog(kAmplitudeReadErr,"");
348 AliWarning("Could not read sample amplitude !");
349 fCount = fSignal = fBunchLength = 0;
353 fSignal = GetNextWord();
361 //_____________________________________________________________________________
362 Int_t AliAltroRawStream::GetPosition()
364 // Sets the position in the
366 // Read the RCU trailer
367 // This includes the trailer size,
368 // RCU identifier and raw data payload.
369 // The RCU trailer format is described
370 // in details in the RCU manual.
372 // We use the last word of the payload
373 // in order to decide which RCU firmware
374 // was used during the data taking.
375 // The firmware v2 adds 0xAAAA as 16
376 // most significant bits and since the
377 // payload size (firmware v1) can not be
378 // that big, we use this as a unique
379 // label of the firmware version.
381 Int_t index = fRawReader->GetDataSize();
382 UInt_t word = Get32bitWord(index);
383 if (((word >> 16) == 0xaaaa) || (word == 2)) {
384 // This is RCU formware v2
385 // The statement word==2 is needed only temporary
386 // in order to be able to read previously generated
389 Int_t trailerSize = 0;
391 AliInfo("Old simulated raw data is assumed!");
396 // First read 32-bit word with the
397 // trailer size (7 bits), RCU ID (9 bits) and
398 // 0xAAA (the rest - 16 bits)
399 fRCUId = (Int_t)((word >> 7) & 0x1ff);
400 trailerSize = (word & 0x7F);
403 // Now read the beginning of the trailer
404 // where the payload size is written
405 if (trailerSize < 2) {
406 fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d bytes",
408 AliWarning(Form("Invalid trailer size found (%d bytes) !",
411 fRCUTrailerSize = (trailerSize-2)*4;
412 index -= fRCUTrailerSize;
414 fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d raw=%d bytes",
416 fRawReader->GetDataSize()));
417 AliWarning(Form("Invalid trailer size found (%d bytes) ! The size is bigger than the raw data size (%d bytes)!",
419 fRawReader->GetDataSize()));
421 fRCUTrailerData = fData + index;
422 Int_t position = Get32bitWord(index);
423 // The size is specified in a number of 40bits
424 // Therefore we need to transform it to number of bytes
427 // Check the consistency of the header and trailer
428 if (((fRawReader->GetDataSize() - trailerSize*4) < position) ||
429 ((fRawReader->GetDataSize() - trailerSize*4) >= (position + 4))) {
430 fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d tr=%d rcu=%d bytes",
431 fRawReader->GetDataSize(),
434 AliWarning(Form("Inconsistent raw data size ! Raw data size - %d bytes (from the header), RCU trailer - %d bytes, raw data paylod - %d bytes !",
435 fRawReader->GetDataSize(),
438 position = fRawReader->GetDataSize() - trailerSize*4;
441 return position * 8 / 10;
444 // In case of the Old RCU trailer format
445 // we have to read just the size of altro payload
446 // in units of 40-bit words
447 Int_t position = (Int_t)word;
451 fRCUTrailerData = NULL;
453 // The size is specified in a number of 40bits
454 // Therefore we need to transform it to number of bytes
457 if (!fIsShortDataHeader) {
459 // Check the consistency of the header and trailer
460 if (((fRawReader->GetDataSize() - 4) < position) ||
461 ((fRawReader->GetDataSize() - 4) >= (position + 4))) {
462 fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
463 fRawReader->GetDataSize()-4,
466 AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
467 fRawReader->GetDataSize()-4,
469 position = fRawReader->GetDataSize()-4;
473 // Check the consistency of the header and trailer
474 // In this case the header is shorter by 4 bytes
475 if ((fRawReader->GetDataSize() < position) ||
476 (fRawReader->GetDataSize() >= (position + 4))) {
477 fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
478 fRawReader->GetDataSize(),
481 AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
482 fRawReader->GetDataSize(),
484 position = fRawReader->GetDataSize();
487 // 7 32-bit words Common Data Header
488 // therefore we have to shift back by 4 bytes
489 // the pointer to the raw data payload
493 // Return the position in units of 10-bit words
494 return position*8/10;
498 //_____________________________________________________________________________
499 UInt_t AliAltroRawStream::Get32bitWord(Int_t &index)
501 // This method returns the 32 bit word at a given
502 // position inside the raw data payload.
503 // The 'index' points to the beginning of the next word.
504 // The method is supposed to be endian (platform)
508 AliFatal("Raw data paylod buffer is not yet initialized !");
512 fRawReader->AddFatalErrorLog(k32bitWordReadErr,Form("pos = %d",index));
514 AliWarning(Form("Invalid raw data payload position (%d) !",index));
518 word = fData[--index] << 24;
519 word |= fData[--index] << 16;
520 word |= fData[--index] << 8;
521 word |= fData[--index];
526 //_____________________________________________________________________________
527 Bool_t AliAltroRawStream::GetRCUTrailerData(UChar_t*& data) const
529 // Return a pointer to the RCU trailer
530 // data. Should be called always after
531 // the RCU trailer was already processed
532 // in the GetPosition() method
533 if (!fRCUTrailerSize || !fRCUTrailerData) {
534 AliError("No valid RCU trailer data is found !");
539 data = fRCUTrailerData;
544 //_____________________________________________________________________________
545 void AliAltroRawStream::PrintDebug() const
547 // The method prints all the available
548 // debug information.
549 // Its is used in case of decoding errors.
551 AliError("Start of debug printout\n--------------------");
554 if (fRawReader) fRawReader->Dump();
556 AliError("End of debug printout\n--------------------");
559 //_____________________________________________________________________________
560 Int_t AliAltroRawStream::GetBranch() const
562 // The method provides the RCU branch index (0 or 1)
563 // for the current hardware address.
564 // In case the hardware address has not been yet
565 // initialized, the method returns -1
566 if (fHWAddress == -1) return -1;
568 return ((fHWAddress >> 11) & 0x1);
571 //_____________________________________________________________________________
572 Int_t AliAltroRawStream::GetFEC() const
574 // The method provides the front-end card index
575 // for the current hardware address.
576 // In case the hardware address has not been yet
577 // initialized, the method returns -1
578 if (fHWAddress == -1) return -1;
580 return ((fHWAddress >> 7) & 0xF);
583 //_____________________________________________________________________________
584 Int_t AliAltroRawStream::GetAltro() const
586 // The method provides the altro chip index
587 // for the current hardware address.
588 // In case the hardware address has not been yet
589 // initialized, the method returns -1
590 if (fHWAddress == -1) return -1;
592 return ((fHWAddress >> 4) & 0x7);
595 //_____________________________________________________________________________
596 Int_t AliAltroRawStream::GetChannel() const
598 // The method provides the channel index
599 // for the current hardware address.
600 // In case the hardware address has not been yet
601 // initialized, the method returns -1
602 if (fHWAddress == -1) return -1;
604 return (fHWAddress & 0xF);
607 //_____________________________________________________________________________
608 void AliAltroRawStream::AddMappingErrorLog(const char *message)
610 // Signal a mapping error
611 // The method can be used by the TPC,PHOS,EMCAL,FMD raw stream
612 // classes in order to log an error related to bad altro mapping
614 if (fRawReader) fRawReader->AddMinorErrorLog(kBadAltroMapping,message);